30 Commits

Author SHA1 Message Date
marfrit 4820e53b18 Merge pull request 'lmcp: 1.1.0 -> 1.1.1 (bug fix: empty inputSchema.properties)' (#24) from claude-noether/marfrit-packages:noether/lmcp-1.1.1 into main
Reviewed-on: marfrit/marfrit-packages#24
2026-05-17 22:47:59 +00:00
test0r 248bef5503 lmcp: 1.1.0 -> 1.1.1 (bug fix: empty inputSchema.properties)
Tracks upstream lmcp v1.1.1 (commit 9707f7a). Single-bug-fix
release: lmcp:tool() now normalises empty inputSchema.properties
by dropping the key, so Zod-strict MCP clients don't reject
tools/list with "expected: record, received: array".

Discovered live on a hertz-tools deployment where two custom
no-arg tools tripped the check and caused Claude Code to mark
the endpoint as disconnected.

New tarball sha256:
  80c2e815aa61a2d3baab051c51cd247bdefa9dd03d72c4867b99c49b6eae9cb9

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 22:47:21 +00:00
marfrit 8a49ac6061 Merge pull request 'lmcp: 1.0.0~rc1 -> 1.1.0 (concurrent dispatch + cancellation + windows sync)' (#23) from claude-noether/marfrit-packages:noether/lmcp-1.1.0 into main
Reviewed-on: marfrit/marfrit-packages#23
2026-05-17 20:22:30 +00:00
test0r 4764f5f37f lmcp: 1.0.0~rc1 -> 1.1.0
Tracks upstream lmcp v1.1.0 (commit 7e62f71). Closes 3 upstream
issues: #11 (progress + cancellation), #18 (windows MSI sync), #20
(concurrent handler dispatch).

Arch:
  pkgver=1.1.0 (no pre-release suffix this time).
  _tag back-translation kept so future rc bumps just need pkgver=X.Y.Z_rcN.

Debian:
  PKGVER=1.1.0 (no ~ suffix).
  Changelog entry summarises the three closed issues + the zero-
  handler-source-changes invariant.

New tarball sha256:
  d758a9504389528cb8940ea81bc8cf47afad8c01166aef3484ac4f5752445532

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 19:44:26 +00:00
marfrit dcb1da2f59 Merge pull request 'lmcp: 0.5.4 -> 1.0.0-rc1 (full MCP 2025-06-18 surface)' (#22) from claude-noether/marfrit-packages:noether/lmcp-1.0.0-rc1 into main 2026-05-17 17:42:16 +00:00
test0r 238c5cee7e lmcp: 0.5.4 -> 1.0.0-rc1 (full MCP 2025-06-18 surface)
Bumps both arch and debian packaging to track upstream v1.0.0-rc1
(commit deb73d1).

Arch (arch/lmcp/PKGBUILD):
  pkgver=1.0.0_rc1 (Arch convention: '_' substitutes for '-' in pre-
  release tags). _tag back-translates for the source URL.

Debian (debian/lmcp/build-deb.sh + changelog):
  PKGVER=1.0.0~rc1 (Debian convention: '~' sorts before the release).
  UPSTREAM_TAG=v1.0.0-rc1 drives the archive URL.

New tarball sha256: 81f9222264371735c196664382460261ef60a259348766bbd6fd2f49ea9d1e7e

What's in 1.0.0-rc1 (full release notes in upstream commit):
  - 14 issues closed
  - new MCP primitives: Resources, Prompts, Completion, Logging,
    Sampling, Roots, fetch, web_search
  - protocol: cursor pagination, structuredContent, _meta, tool
    annotations, protocolVersion bump to 2025-06-18
  - transports: stdio (LMCP_TRANSPORT=stdio), full Streamable HTTP
    rewrite with sessions, persistent SSE, server-initiated requests
  - json.lua: UTF-16 surrogate pairs + empty_object sentinel
  - backwards-compatible with every existing sessionless-POST client

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 17:18:18 +00:00
marfrit 70c943e948 Merge pull request 'ffmpeg-v4l2-request-git → ffmpeg-v4l2-request-fourier (dir rename)' (#20) from claude-noether/marfrit-packages:noether/rename-ffmpeg-dir into main
Reviewed-on: marfrit/marfrit-packages#20
2026-05-16 23:08:10 +00:00
claude-noether d6c4260eb8 ffmpeg-v4l2-request-git → ffmpeg-v4l2-request-fourier: rename directory
PKGBUILD already renamed itself (pkgname=ffmpeg-v4l2-request-fourier,
replaces=(ffmpeg ffmpeg-v4l2-request-git)) but the containing
directory was never moved. This commit completes the rename to align
the path with the package identity and the rest of the -fourier
umbrella (libva, mpv, kwin, qt6-base, chromium, linux-*).

CI workflow path-trigger is wildcard (arch/**), unaffected. Step
names + cp source path updated to the new directory.
2026-05-17 01:04:37 +02:00
marfrit 1fed626900 Merge pull request 'libva-v4l2-request-ohm-gl-fix: mark deprecated' (#19) from claude-noether/marfrit-packages:noether/deprecate-ohm-gl-fix into main
Reviewed-on: marfrit/marfrit-packages#19
2026-05-16 23:01:00 +00:00
claude-noether 0b2393cecc libva-v4l2-request-ohm-gl-fix: mark deprecated, point at -fourier
Predecessor experimental package (tarball + 18 stacked patches) is
superseded by libva-v4l2-request-fourier (git-tracked fork tip,
iter38 multi-device probe). The successor already declares
replaces=('libva-v4l2-request-ohm-gl-fix') so installs migrate
automatically; this commit just makes the deprecation visible in
README + pkgdesc.

Kept in-tree as historical reference for the ohm_gl_fix Phase 6
audit trail.
2026-05-17 01:00:25 +02:00
marfrit 697413103d Merge pull request 'libva-v4l2-request-fourier: -Db_lto=false (closes #17)' (#18) from claude-noether/marfrit-packages:noether/libva-disable-lto into main 2026-05-16 16:39:57 +00:00
claude-noether b648276122 libva-v4l2-request-fourier: -Db_lto=false (closes #17)
CI binary segfaulted on HEVC vaEndPicture even though
/etc/makepkg.conf has OPTIONS=(... !lto ...). Root cause: arch-meson's
wrapper hard-codes `-D b_lto=true` regardless of makepkg.conf, so
the binary still gets cross-function ICF (Identical Code Folding)
under -O2 + LTO.

HEVC is the only codec in the campaign that submits a per-frame chain
of 4 control structs (SPS + PPS + DECODE_PARAMS + SLICE_PARAMS); ICF
finds a near-duplicate per-codec helper across the codec dispatch and
merges them, then the wrong instance's local stack layout is invoked
on the HEVC path → SEGV. The other 4 codecs (H.264, VP8, VP9, MPEG-2)
submit fewer/simpler control structs and tolerate the folding by
accident.

Empirical confirmation from the issue body's binary bisection:

  meson build (default debugoptimized)     485 KB   HEVC ✓
  arch-meson + --buildtype=release          145 KB   HEVC ✓
  arch-meson + release + -flto              76 KB   HEVC SEGV
  CI build (this package, 7ac934e-1)        133 KB   HEVC SEGV

Fix: append `-Db_lto=false` to the arch-meson invocation.
pkgrel 1 -> 2.
2026-05-15 19:03:46 +00:00
marfrit 2e2c9b6361 linux-ampere-fourier: chmod +x prebuild.sh (#16) 2026-05-15 17:20:10 +00:00
claude-noether 0d311d61b4 linux-ampere-fourier: chmod +x prebuild.sh
The exec bit was missing on prebuild.sh as committed in PR #15
(it landed mode 0644). Running './prebuild.sh' fails with
'Permission denied'; bash ./prebuild.sh works as a workaround but
the shebang is intended to do its job.

Caught while running the first linux-ampere-fourier build on
boltzmann today. README.md examples show './prebuild.sh' so users
will hit the same error.

Single-bit fix via git update-index --chmod=+x. No content change.
2026-05-15 16:54:29 +00:00
marfrit efc1bfd66a linux-ampere-fourier: bootstrap PKGBUILD (CoolPi GenBook RK3588) (#15) 2026-05-15 16:49:45 +00:00
claude-noether 154fa2f14a linux-ampere-fourier: bootstrap PKGBUILD (CoolPi GenBook RK3588)
Sibling to kernel-agent PR #8 which lands the scope-tagged board
patches + fleet/ampere.yaml manifest. This PR carries the
makepkg-side recipe.

## Baseline

marfrit/linux-rk3588-marfrit @ f8f3ad9 (mainline v7.0-rc3 + 18 commits):
  10 by Markus Fritsche  (board DTS + Kconfig + suspend/wakeup + bt)
   4 by Shawn Lin        (phy: rockchip-snps-pcie3 stability)
   2 by Cristian Ciocaltea (clk + dw-dp bridge — Collabora)
   1 by Sebastian Reichel (Rock 5 ITX hdmirx — unused by ampere)
   1 by Pedro Alves      (CLK_SET_RATE_PARENT VOP2 fix)

The 6 board-relevant patches (pwm15 pinctrl + RK806 power-off +
genbook pwm-fan/speaker/USB-C/lid) are scope-tagged in
kernel-agent. The 12 others are 'cherry-picks-in-baseline'
currently — splitting them into scope-tagged patches is a
follow-up.

## Source distribution

The kernel tree isn't pushable to Gitea (boltzmann's working clone
is shallow). Tarball (260MB) doesn't belong in marfrit-packages
either. Pragmatic shortcut: ship prebuild.sh that produces the
tarball locally from $LINUX_RK3588_MARFRIT_TREE (default
~/src/linux-rockchip) just before makepkg runs. PKGBUILD source
array references the tarball by name; makepkg picks it up from
the PKGBUILD dir.

Build flow:
  cd arch/linux-ampere-fourier
  ./prebuild.sh           # produces 260MB tarball; idempotent w/ sha check
  makepkg -s --noconfirm

Future iteration: host the tarball on Gitea release assets or
packages.reauktion.de/sources/ and switch source to URL.

## What the PR ships

  PKGBUILD                          — the recipe (linux-rk3588-marfrit @ f8f3ad9)
  config                            — snapshot of ampere's /proc/config.gz
  linux-ampere-fourier.preset       — mkinitcpio preset, /boot/firmware/ paths
  extlinux-add.hook                 — alpm hook, fires on /boot/firmware/Image* changes
  extlinux-add.sh                   — idempotent managed-label injector for
                                     /boot/firmware/extlinux/extlinux.conf
                                     (vfat on mmcblk0p1, ampere-specific path)
  prebuild.sh                       — source-staging helper (see above)
  README.md                         — build + install runbook

## ampere-specific boot path differences vs fresnel

ampere boots from /boot/firmware/ (vfat partition), not /boot/ (root
partition) like fresnel. The PKGBUILD installs Image + initramfs + DTB
under /boot/firmware/ directly. The extlinux-add hook fires on
/boot/firmware/<X> path changes and edits
/boot/firmware/extlinux/extlinux.conf. The mkinitcpio preset writes
initramfs to /boot/firmware/.

Only one PRESET ('default') — no fallback image — because
/boot/firmware is ~1G total and two ~20MB initramfs files plus the
DTB and a couple of kernel-image backups would squeeze it tight.

## Out of scope this PR

- Ask 2 (VP9 enablement) and Ask 3 (AV1 dec) from kernel-agent issue #6
- Build + publish + install (sequenced after this PR + kernel-agent PR #8 merge)
- Splitting the 12 non-board commits into scope-tagged kernel-agent patches
2026-05-15 16:19:24 +00:00
marfrit 2af63ce988 Merge pull request 'linux-fresnel-fourier: 7.0-1 -> 7.0-14 (carry vb2_dma_resv RFC v2 series)' (#14) from claude-noether/marfrit-packages:noether/linux-fresnel-fourier-pkgrel14 into main
Reviewed-on: marfrit/marfrit-packages#14
2026-05-15 15:37:23 +00:00
claude-noether e9bc6ebd27 linux-fresnel-fourier: 7.0-1 -> 7.0-14 (carry vb2_dma_resv RFC v2 series)
Sibling to kernel-agent PR #7 (which lands the vb2_dma_resv RFC v2
series under patches/subsystem/media/videobuf2/ and updates
fleet/fresnel.yaml to include them). This PR carries the same three
patches in the build-tree-ready form for the linux-fresnel-fourier
PKGBUILD.

Background: Markus iterated v2 locally on boltzmann reaching pkgrel=14
since the 2026-05-09 bootstrap published 7.0-1. v2 attaches the V4L2
producer fence at device_run in slept-OK context per Dufresne's v1
review on linux-media. Drivers opted in here: hantro + rockchip-rga.

Changes:
- pkgrel 1 -> 14
- pkgdesc adds '+ vb2_dma_resv RFC v2'
- source array gains 3 new local patch files (scope-tagged comments
  point to where they live in marfrit/kernel-agent)
- sha256sums extended to 11 SKIP entries

No prepare() edit needed — the existing for-loop applies every *.patch
in $srcdir, so the 4/5/6 patches get picked up automatically. config
unchanged (verified diff vs boltzmann's local pkgrel=14 tree).

Pre-built artifacts: linux-fresnel-fourier-7.0-14-aarch64.pkg.tar.zst
and linux-fresnel-fourier-headers-7.0-14-aarch64.pkg.tar.zst already
exist on boltzmann at /home/mfritsche/src/kernel-agent-bootstrap/
build/marfrit-packages/arch/linux-fresnel-fourier/ — will be signed
and published via marfrit-publish-arch after this PR merges (no fresh
compile needed; the artifacts were built locally during the iteration
loop that reached pkgrel=14).
2026-05-15 15:33:55 +00:00
marfrit 201e671d61 Merge pull request 'firefox-fourier: vendor-prefs install path correction (browser/defaults -> defaults)' (#13) from claude-noether/marfrit-packages:noether/firefox-fourier-vendor-prefs-correct-path into main
Reviewed-on: marfrit/marfrit-packages#13
2026-05-15 14:23:32 +00:00
claude-noether d63d1cef72 firefox-fourier: move vendor-prefs to defaults/preferences/ (the path Firefox actually scans)
Empirical follow-up to #9. After packaging 150.0.1-4 and installing on
fresnel, MOZ_LOG showed the failure pattern was still present:

  D/FFmpegVideo FFMPEG: Using preferred software codec h264

No VAAPI_VLD engagement, no dmabuf surface locking — Gecko bailed
before reaching the patched VAAPI path. Same symptom as issue #8
pre-fix, despite the prefs file being on disk at the expected path.

Root cause: /usr/lib/firefox-fourier/browser/defaults/preferences/ is
NOT a vendor-prefs scan location in Firefox 150. Mozilla's canonical
scan dir is /usr/lib/<app>/defaults/preferences/ — without the
'browser/' prefix.

Verified by hand-copying the same file to /usr/lib/firefox-fourier/
defaults/preferences/ and re-running the H.264 playback test:

  D/FFmpegVideo FFMPEG: Requesting pixel format VAAPI_VLD
  D/Dmabuf VideoFrameSurface: VAAPI locking dmabuf surface UID 26267
    FFMPEG ID 0x4000000 mAVHWFrameContext ...
  D/Dmabuf VideoFrameSurface: VAAPI locking dmabuf surface UID 26268
    FFMPEG ID 0x4000001 ...
  (15+ surface locks)

End-to-end zero-copy DMABUF path engaged, hantro/rkvdec dekodes the
H.264 stream via libva-v4l2-request-fourier iter38b.

pkgrel 4 -> 5. No other PKGBUILD changes.
2026-05-15 14:18:09 +00:00
marfrit 108c725c58 Merge pull request 'kwin-fourier 6.6.4->6.6.5 + qt6-base-fourier 6.11.0->6.11.1 (track upstream extra)' (#12) from claude-noether/marfrit-packages:noether/kwin-qt6-baseline-bump into main
Reviewed-on: marfrit/marfrit-packages#12
2026-05-15 11:45:27 +00:00
claude-noether 75dadb2925 qt6-base-fourier: rebase 6.11.0 -> 6.11.1 to track upstream extra
Triggered by 'pacman -Syu' on fresnel showing local 1:6.11.0-2 newer
than (then-)extra 6.11.0-4. By the time of this commit Arch has moved
on to 6.11.1-1; rebase straight to that.

Diff against Arch's qt6-base 6.11.1 PKGBUILD reduced:
- _pkgver 6.11.0 -> 6.11.1
- pkgrel 3 -> 1 (reset on pkgver bump)
- sha256 of git tag updated to 2eafe504... (matches Arch's 6.11.1 PKGBUILD)
- Drop cherry-pick of 8b54513cdcf6 (qdbus crash fix landed upstream
  in 6.11.1; Arch dropped it from theirs as well)
- depends: gcc-libs replaced by libgcc + libstdc++ (Arch split these
  into separate packages between 6.11.0 and 6.11.1)
- Build flag: -DFEATURE_sql_ibase=OFF removed, -DFEATURE_mimetype_database=OFF
  added (Arch toggled in 6.11.1)

Kept (the reason this fork exists):
- 0001/0002/0003 GL_R8-on-ES3 patches (Mali GLES3 KWin compositor stall fix)
- qt6-base-cflags.patch + qt6-base-nostrip.patch (system CFLAGS + skip strip)
- qt6-xcb-private-headers-fourier sub-package (depended on by other fork pkgs)
- epoch=1 (precedence guarantee until upstream lands GL_R8/ES3 fix)

Patches NOT dry-run-verified against 6.11.1 source (qt clone is multi-GB
and impractical to fetch for a quick check). They touch glyph cache and
RHI gles2 paths that have been stable since Qt 6.10; expected to apply
cleanly. Will revert pkgrel and re-pin if first build hits hunk failures.
2026-05-15 10:57:02 +00:00
claude-noether fedcc4a357 kwin-fourier: 6.6.4 -> 6.6.5 (track upstream extra)
Triggered by 'pacman -Syu' on fresnel showing local 1:6.6.4-1 newer
than extra 6.6.5-1 (epoch wins, but our base lags upstream).

- pkgver 6.6.4 -> 6.6.5
- pkgrel 3 -> 1 (reset on pkgver bump)
- sha256sum updated for new tarball
- 0001-transaction-bypass-watchDmaBuf-fence-wait.patch dry-run verified
  clean against 6.6.5/src/wayland/transaction.cpp

Epoch=1 retained until upstream lands a proper V4L2 implicit-sync
fence-wait bypass (the patch-header hypothesis is still being tested
through ohm/fresnel HW-decode validation; not upstreamable yet).
2026-05-15 10:53:59 +00:00
marfrit 860ebf2df5 firefox-fourier: flatten patches to top-level (makepkg has no subdir support) (#11) 2026-05-15 08:04:12 +00:00
claude-noether 109858eae5 firefox-fourier: flatten patches to top-level (makepkg has no subdir support)
Follow-up to #10. The subdir layout I assumed worked turned out to not
work — per 'man PKGBUILD':

  The filename in the array must NOT include any path components like ./

makepkg's source-staging only honors basenames; the patches/ subdir
references staged the files but the basename-lookup at apply time
failed with the same 'not found in build directory' error that #9 hit.

I copied the chromium-fourier convention thinking it was proven, but
chromium-fourier has no CI either and likely has the same latent
breakage (separate issue, not in this PR's scope).

The actually-working pattern is the mpv-fourier one: patches at the
top level next to the PKGBUILD. mpv-fourier iter2 just built green
on CI (#92) with that layout.

This commit:
- Moves all 8 patches (5 fourier + 3 arch upstream) from patches/
  to arch/firefox-fourier/ via git mv (preserves blame).
- Removes the now-empty patches/ subdir.
- Strips 'patches/' prefix from source array entries.
- Strips '/patches' from prepare() patch -i paths.

No semantic change to the patch content or apply order.

pkgrel 3 -> 4.
2026-05-15 08:00:27 +00:00
marfrit 9041c1bf51 firefox-fourier: fix patches layout + ship missing arch upstream patches (#10) 2026-05-15 07:56:58 +00:00
claude-noether f41e9a117b firefox-fourier: fix patches layout — ship arch-*.patch + reference patches/
The PKGBUILD has been structurally broken since at least the 150.0.1
import: source array referenced patches at top level ('0001-...patch')
but the actual files live in patches/ — makepkg searched for them in
the package root and failed before doing any work. The arch-0002/3/4
upstream toolchain patches (clang 22, glibc 2.43, Rust 1.95) weren't
shipped in the repo at all.

Caught when boltzmann tried to build 150.0.1-2 (PR #9 follow-up); fails
at the source-staging phase with:

  ==> ERROR: arch-0002-Bug-2033279-Make-enable-rust-simd-work-with-Rust-1.9.patch
              was not found in the build directory and is not a URL.

Why nobody noticed: firefox-fourier has no Gitea Actions job (too heavy
for the runner pool). The shipped 150.0.1-1 .pkg.tar.zst was produced
by hand-staging files; the PKGBUILD itself never reproduced from a
clean checkout.

This commit:
- Moves all source-array patch references under patches/ to match the
  on-disk layout (same convention as chromium-fourier).
- Updates prepare() paths accordingly.
- Adds arch-0002/3/4 patches fetched verbatim from
  https://gitlab.archlinux.org/archlinux/packaging/packages/firefox
  (raw/main/{0002,0003,0004}-...patch). Renamed with arch- prefix in
  the repo to avoid namespace collision with the local 0001..0005.
- Adds the previously-omitted 0005-rdd-sandbox-v4l2-media-ctl.patch
  to the source array + prepare(); this is the patch that broadens
  the RDD sandbox so /dev/media* and /dev/video* ioctls reach the
  decoder child (README §1 enumerates it as load-bearing for the HW
  path). It was present in patches/ but not wired up.

Dry-run verified all 8 patches apply cleanly against firefox-150.0.1
source (some hunks offset by ≤3 lines, no conflicts).

pkgrel 2 -> 3.
2026-05-15 07:24:30 +00:00
marfrit 2f78136479 Merge pull request 'fresnel-fourier stack: bump libva to iter38b + fix firefox HW-decode defaults (#8)' (#9) from claude-noether/marfrit-packages:noether/libva-iter38b-and-firefox-prefs into main
Reviewed-on: marfrit/marfrit-packages#9
2026-05-15 06:13:19 +00:00
claude-noether 62a594ab59 firefox-fourier: ship RK3399 HW-decode default prefs (closes #8)
Three prefs that gate the patched VAAPI / V4L2-request code path are
'false' upstream and need to be 'true' for the libva-v4l2-request
backend to actually engage on RK3399 / panfrost EGL:

  widget.dmabuf.force-enabled
  media.hardware-video-decoding.force-enabled
  media.ffvpx-hw.enabled

Without them, Gecko's DMA-BUF probe silently fails (panfrost EGL
doesn't trip the right detection), the (Intel-tuned) HW-vs-SW cost
heuristic picks SW, and the FFvpx PDM never selects its HW-capable
variant for VP8/VP9. Net result: fresh profiles SW-decode despite the
0001..0004 unlock patches being applied.

Shipped as a vendor-default file at:
  /usr/lib/firefox-fourier/browser/defaults/preferences/rockchip-fourier-defaults.js

Lower precedence than user.js / about:config — power users debugging
HW decode can still flip them off without touching the package.

pkgrel 1 -> 2.

Closes: #8
2026-05-15 06:10:01 +00:00
claude-noether 81cc050bf3 libva-v4l2-request-fourier: bump pin iter8 -> iter38b (7ac934e)
Carries the fork from libva-multiplanar iter8 close (2026-05-06) to
fresnel-fourier iter38b (2026-05-14): multi-device probe so a single
libva session serves rkvdec (H.264 + HEVC + VP9) + hantro (MPEG-2 +
VP8) without LIBVA_V4L2_REQUEST_VIDEO_PATH overrides, plus the
MAX_PROFILES bounds-check fix from iter38b.

Required by the fresnel-fourier README's HW-decode stack (vainfo
exposes all 10 profiles in one session, byte-exact bench verified
across 5 codecs).

68 commits between the old pin (65969da3) and the new (7ac934e0).
pkgver() recomputes the rev count at build time; the static placeholder
is bumped from r280 to r348 to reflect the new pin.
2026-05-15 06:08:21 +00:00
32 changed files with 17182 additions and 41 deletions
+4 -4
View File
@@ -375,7 +375,7 @@ jobs:
run: rm -f /root/repo_pass /root/.ssh/id_ed25519 run: rm -f /root/repo_pass /root/.ssh/id_ed25519
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# ffmpeg-v4l2-request-git (aarch64 only) — FFmpeg with V4L2 Request API # ffmpeg-v4l2-request-fourier (aarch64 only) — FFmpeg with V4L2 Request API
# hwaccel for Rockchip / Allwinner stateless decoders. Used by the Fourier # hwaccel for Rockchip / Allwinner stateless decoders. Used by the Fourier
# umbrella (ohm, fresnel, ampere). Long-running build, so failures don't # umbrella (ohm, fresnel, ampere). Long-running build, so failures don't
# block downstream debian jobs. # block downstream debian jobs.
@@ -416,11 +416,11 @@ jobs:
chmod 600 /root/.ssh/id_ed25519 chmod 600 /root/.ssh/id_ed25519
ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null
- name: makepkg ffmpeg-v4l2-request-git - name: makepkg ffmpeg-v4l2-request-fourier
run: | run: |
set -e set -e
rm -rf /tmp/build-ffmpeg-v4l2 rm -rf /tmp/build-ffmpeg-v4l2
cp -r arch/ffmpeg-v4l2-request-git /tmp/build-ffmpeg-v4l2 cp -r arch/ffmpeg-v4l2-request-fourier /tmp/build-ffmpeg-v4l2
chown -R builder:builder /tmp/build-ffmpeg-v4l2 chown -R builder:builder /tmp/build-ffmpeg-v4l2
cd /tmp/build-ffmpeg-v4l2 cd /tmp/build-ffmpeg-v4l2
# Parallelise wide; distcc-avahi distributes compiles across the # Parallelise wide; distcc-avahi distributes compiles across the
@@ -429,7 +429,7 @@ jobs:
makepkg --nocheck --noconfirm --syncdeps --cleanbuild makepkg --nocheck --noconfirm --syncdeps --cleanbuild
ls -la *.pkg.tar.* | grep -v "\.sig$" ls -la *.pkg.tar.* | grep -v "\.sig$"
- name: sign ffmpeg-v4l2-request-git - name: sign ffmpeg-v4l2-request-fourier
run: | run: |
set -e set -e
cd /tmp/build-ffmpeg-v4l2 cd /tmp/build-ffmpeg-v4l2
+22 -2
View File
@@ -13,7 +13,7 @@
pkgname=firefox-fourier pkgname=firefox-fourier
pkgver=150.0.1 pkgver=150.0.1
pkgrel=1 pkgrel=5
pkgdesc='Firefox with V4L2 stateless HW video decode unlocked for mainline Linux Rockchip' pkgdesc='Firefox with V4L2 stateless HW video decode unlocked for mainline Linux Rockchip'
arch=('aarch64' 'x86_64') arch=('aarch64' 'x86_64')
url='https://www.mozilla.org/firefox' url='https://www.mozilla.org/firefox'
@@ -87,8 +87,12 @@ source=(
'0002-libwrapper-hwdevice-ctx-create.patch' '0002-libwrapper-hwdevice-ctx-create.patch'
'0003-ffmpegvideo-v4l2-request-route.patch' '0003-ffmpegvideo-v4l2-request-route.patch'
'0004-prefs-v4l2-request.patch' '0004-prefs-v4l2-request.patch'
'0005-rdd-sandbox-v4l2-media-ctl.patch'
# Vendor-default prefs that gate the patched VAAPI path on RK3399 —
# widget.dmabuf.force-enabled etc. See marfrit-packages#8 for evidence.
'rockchip-fourier-defaults.js'
) )
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP') sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
prepare() { prepare() {
cd "${srcdir}/firefox-${pkgver}" cd "${srcdir}/firefox-${pkgver}"
@@ -103,6 +107,7 @@ prepare() {
patch -Np1 -i "${srcdir}/0002-libwrapper-hwdevice-ctx-create.patch" patch -Np1 -i "${srcdir}/0002-libwrapper-hwdevice-ctx-create.patch"
patch -Np1 -i "${srcdir}/0003-ffmpegvideo-v4l2-request-route.patch" patch -Np1 -i "${srcdir}/0003-ffmpegvideo-v4l2-request-route.patch"
patch -Np1 -i "${srcdir}/0004-prefs-v4l2-request.patch" patch -Np1 -i "${srcdir}/0004-prefs-v4l2-request.patch"
patch -Np1 -i "${srcdir}/0005-rdd-sandbox-v4l2-media-ctl.patch"
cp "${srcdir}/mozconfig" .mozconfig cp "${srcdir}/mozconfig" .mozconfig
} }
@@ -160,4 +165,19 @@ export MOZ_X11_EGL="${MOZ_X11_EGL:-1}"
exec /usr/lib/firefox-fourier/firefox-fourier "$@" exec /usr/lib/firefox-fourier/firefox-fourier "$@"
LAUNCHER LAUNCHER
chmod 0755 "${pkgdir}/usr/bin/firefox-fourier" chmod 0755 "${pkgdir}/usr/bin/firefox-fourier"
# Vendor-default prefs (RK3399 HW-decode unlock) — closes #8.
# Lower precedence than user prefs / about:config; loaded by Firefox
# at startup from the package install dir. The 0004 patch covers
# media.ffmpeg.v4l2-request.enabled; this file covers the three
# additional prefs that gate the path to the patched code.
# Vendor-prefs install path: /usr/lib/firefox-fourier/defaults/preferences/
# (Mozilla's canonical scan dir for third-party default-pref drops.) The
# browser/defaults/preferences/ alternative looked promising but is NOT a
# vendor-prefs scan location in Firefox 150 — empirically confirmed on
# fresnel: file shipped there, VAAPI never engaged. Same file under
# defaults/preferences/ → MOZ_LOG showed `Requesting pixel format
# VAAPI_VLD` + dmabuf surfaces locking end-to-end.
install -Dm644 "${srcdir}/rockchip-fourier-defaults.js" \
"${pkgdir}/usr/lib/firefox-fourier/defaults/preferences/rockchip-fourier-defaults.js"
} }
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alex Hochheiden <ahochheiden@mozilla.com>
Date: Wed, 1 Apr 2026 18:11:37 +0000
Subject: [PATCH] Bug 2023597 - Use `wasm32-wasip1` target for clang >= 22.1
r=firefox-build-system-reviewers,sergesanspaille
https://github.com/llvm/llvm-project/pull/165345
https://releases.llvm.org/22.1.0/tools/clang/docs/ReleaseNotes.html
Differential Revision: https://phabricator.services.mozilla.com/D291023
---
build/moz.configure/toolchain.configure | 3 +++
1 file changed, 3 insertions(+)
diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
index a37ed610cc43..c7d0c8bdf75c 100644
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -695,6 +695,9 @@ def check_compiler(configure_cache, compiler, language, target, android_version)
# This makes clang define __ANDROID_API__ and use versioned library
# directories from the NDK.
toolchain = "%s%d" % (target.toolchain, android_version)
+ elif target.kernel == "WASI" and info.type == "clang" and info.version >= Version("22.1"):
+ # The wasm32-wasi target was renamed to wasm32-wasip1 in LLVM 22.1.
+ toolchain = "wasm32-wasip1"
else:
toolchain = target.toolchain
@@ -0,0 +1,19 @@
// firefox-fourier — RK3399 V4L2-stateless HW-decode default prefs.
//
// The patch series (0001..0004) builds the VAAPI / V4L2-request routing
// path through libavcodec, but the resulting code path is gated by three
// other prefs that are 'false' upstream because the relevant probes don't
// fire on panfrost EGL or trip the Intel-tuned cost heuristic. Without
// these, firefox-fourier silently SW-decodes on a fresh profile despite
// having all the unlock patches applied.
//
// Filed via marfrit/marfrit-packages#8 — see that issue for MOZ_LOG
// evidence on fresnel (Pinebook Pro / RK3399).
//
// These are *vendor* defaults: lower precedence than user.js and
// about:config user prefs. Power users who want to disable HW decode for
// debugging can flip them in user prefs without touching this file.
pref("widget.dmabuf.force-enabled", true);
pref("media.hardware-video-decoding.force-enabled", true);
pref("media.ffvpx-hw.enabled", true);
+4 -4
View File
@@ -2,7 +2,7 @@
# Upstream maintainers: Felix Yan, Antonio Rojas # Upstream maintainers: Felix Yan, Antonio Rojas
# Contributor: Andrea Scarpino <andrea@archlinux.org> # Contributor: Andrea Scarpino <andrea@archlinux.org>
# #
# kwin-fourier — KWin 6.6.4 with the V4L2-stateless implicit-sync # kwin-fourier — KWin 6.6.5 with the V4L2-stateless implicit-sync
# transaction wait bypass. Hypothesis: KWin's # transaction wait bypass. Hypothesis: KWin's
# `Transaction::watchDmaBuf` calls DMA_BUF_IOCTL_EXPORT_SYNC_FILE on # `Transaction::watchDmaBuf` calls DMA_BUF_IOCTL_EXPORT_SYNC_FILE on
# every plane of every imported dmabuf and parks the transaction on a # every plane of every imported dmabuf and parks the transaction on a
@@ -21,9 +21,9 @@
# ../chromium-fourier/KWIN_PIVOT.md for the full diagnosis thread. # ../chromium-fourier/KWIN_PIVOT.md for the full diagnosis thread.
pkgname=kwin-fourier pkgname=kwin-fourier
pkgver=6.6.4 pkgver=6.6.5
_dirver=$(echo $pkgver | cut -d. -f1-3) _dirver=$(echo $pkgver | cut -d. -f1-3)
pkgrel=3 pkgrel=1
_upname=kwin _upname=kwin
epoch=1 epoch=1
arch=(aarch64 x86_64) arch=(aarch64 x86_64)
@@ -103,7 +103,7 @@ conflicts=(kwin)
replaces=(kwin) replaces=(kwin)
source=(https://download.kde.org/stable/plasma/$_dirver/$_upname-$pkgver.tar.xz{,.sig} source=(https://download.kde.org/stable/plasma/$_dirver/$_upname-$pkgver.tar.xz{,.sig}
0001-transaction-bypass-watchDmaBuf-fence-wait.patch) 0001-transaction-bypass-watchDmaBuf-fence-wait.patch)
sha256sums=('3f9439760580a977d018daf4b35b62e5a1700def7b21c8dfbfc789d21378d7ad' sha256sums=('6c187ce7a5506090b438ef900103836fa0537674dde8b31e5b497ef321643cb4'
'SKIP' 'SKIP'
'SKIP') 'SKIP')
validpgpkeys=('E0A3EB202F8E57528E13E72FD7574483BB57B18D' # Jonathan Esk-Riddell <jr@jriddell.org> validpgpkeys=('E0A3EB202F8E57528E13E72FD7574483BB57B18D' # Jonathan Esk-Riddell <jr@jriddell.org>
+26 -12
View File
@@ -6,8 +6,11 @@
# tracks the campaign fork's git history directly, so iteration sweeps # tracks the campaign fork's git history directly, so iteration sweeps
# (DEBUG removal, follow-up bugfixes) land in a clean linear log. # (DEBUG removal, follow-up bugfixes) land in a clean linear log.
# #
# Campaign: ~/src/libva-multiplanar/ (eight closed iterations as of # Campaign: ~/src/libva-multiplanar/ (iter8 close 2026-05-06) plus
# 2026-05-06; iter8 close is the production tip pinned below). # ~/src/fresnel-fourier/ which carried the fork to iter38b — multi-device
# probe so a single libva session serves all 5 codecs (rkvdec H.264 +
# HEVC + VP9, hantro MPEG-2 + VP8) plus a bounds-check fix for
# MAX_PROFILES. Pinned below.
# Fork repo: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier # Fork repo: https://git.reauktion.de/marfrit/libva-v4l2-request-fourier
# Bootlin upstream: https://github.com/bootlin/libva-v4l2-request # Bootlin upstream: https://github.com/bootlin/libva-v4l2-request
# #
@@ -20,17 +23,20 @@
pkgname=libva-v4l2-request-fourier pkgname=libva-v4l2-request-fourier
_upstreampkg=libva-v4l2-request _upstreampkg=libva-v4l2-request
# Pin the fork tip. 65969da = "iter8 Phase 4: tests/run_perf_binding_cell.sh" # Pin the fork tip. 7ac934e = "iter38b: bounds check uses MAX_PROFILES
# — last commit on master before fresnel-fourier work started layering # (11), not MAX_CONFIG_ATTRIBUTES (10)" — fresnel-fourier campaign
# MPEG-2 rewrites on top of it (2026-05-08). The libva-multiplanar campaign # production tip 2026-05-14, sibling iter38 added multi-device probe so
# closed iter8 at this commit; promote to a later pin only after a future # a single libva session serves rkvdec + hantro without requiring
# iteration closes cleanly. # LIBVA_V4L2_REQUEST_VIDEO_PATH overrides. Promote to a later pin only
_commit=65969da3ee901442a8ca4e1f7f9697d5461d368a # after a future iteration closes cleanly.
_commit=7ac934e0c5420814c7a5fc3e2a2f08251d590d9e
# Project version from meson.build (1.0.0) + commit count + short sha, # Project version from meson.build (1.0.0) + commit count + short sha,
# matching the ffmpeg-v4l2-request-fourier convention. # matching the ffmpeg-v4l2-request-fourier convention. Recomputed at
pkgver=1.0.0.r280.65969da # build time by pkgver() below; the static value here is a placeholder
pkgrel=1 # so AUR-style consumers see something coherent before src/ exists.
pkgver=1.0.0.r348.7ac934e
pkgrel=2
pkgdesc="VA-API backend for V4L2 stateless decoders (multiplanar fork — fourier umbrella)" pkgdesc="VA-API backend for V4L2 stateless decoders (multiplanar fork — fourier umbrella)"
arch=('aarch64') arch=('aarch64')
url="https://git.reauktion.de/marfrit/libva-v4l2-request-fourier" url="https://git.reauktion.de/marfrit/libva-v4l2-request-fourier"
@@ -55,7 +61,15 @@ build() {
cd "${srcdir}/${_upstreampkg}-fourier" cd "${srcdir}/${_upstreampkg}-fourier"
# meson_options.txt only exposes 'kernel_headers' — leave it empty to # meson_options.txt only exposes 'kernel_headers' — leave it empty to
# use system /usr/include kernel UAPI headers. No per-codec toggles. # use system /usr/include kernel UAPI headers. No per-codec toggles.
arch-meson build --buildtype=release #
# b_lto=false: override arch-meson's wrapper default of `-D b_lto=true`,
# which the makepkg.conf OPTIONS=(..., !lto, ...) line does NOT actually
# override (arch-meson hard-codes b_lto=true). The hand-built reproducer
# from issue #17 shows: LTO/ICF kernel-folds per-codec helpers and HEVC's
# multi-control-struct chain (SPS+PPS+DECODE_PARAMS+SLICE_PARAMS) gets a
# wrong helper-instance pulled in at vaEndPicture → segfault. The 4 other
# codecs (single-control-struct) tolerate the folding by accident.
arch-meson build --buildtype=release -Db_lto=false
meson compile -C build meson compile -C build
} }
+8 -1
View File
@@ -1,6 +1,13 @@
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com> # Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
# Campaign: ohm_gl_fix Phase 6 Step 1 # Campaign: ohm_gl_fix Phase 6 Step 1
# #
# DEPRECATED (2026-05-16): superseded by ../libva-v4l2-request-fourier/
# which tracks the campaign fork's git history directly and adds the
# iter38 multi-device probe (single libva session for rkvdec H.264/HEVC/VP9
# + hantro MPEG-2/VP8). The successor declares
# replaces=('libva-v4l2-request-ohm-gl-fix'), so installing it removes
# this package automatically. See README.md for the full deprecation note.
#
# Forks libva-v4l2-request to add hantro-vpu multiplanar + modern # Forks libva-v4l2-request to add hantro-vpu multiplanar + modern
# stateless UAPI support. Conflicts/replaces stock libva-v4l2-request. # stateless UAPI support. Conflicts/replaces stock libva-v4l2-request.
# #
@@ -11,7 +18,7 @@ pkgname=libva-v4l2-request-ohm-gl-fix
_upstreampkg=libva-v4l2-request _upstreampkg=libva-v4l2-request
pkgver=1.0.0.r0.ga3c2476 pkgver=1.0.0.r0.ga3c2476
pkgrel=2 pkgrel=2
pkgdesc="VA-API backend for V4L2 stateless decoders, hantro-vpu multiplanar fork" pkgdesc="DEPRECATED — use libva-v4l2-request-fourier. VA-API backend for V4L2 stateless decoders, hantro-vpu multiplanar fork"
arch=('aarch64') arch=('aarch64')
url="https://github.com/bootlin/libva-v4l2-request" url="https://github.com/bootlin/libva-v4l2-request"
license=('LGPL2.1' 'MIT') license=('LGPL2.1' 'MIT')
@@ -1,5 +1,24 @@
# libva-v4l2-request-ohm-gl-fix # libva-v4l2-request-ohm-gl-fix
> ## ⚠ DEPRECATED — use [`libva-v4l2-request-fourier`](../libva-v4l2-request-fourier/) instead
>
> This package is the **predecessor experimental** build (tarball pin
> + 18 stacked patches) and is no longer maintained as of 2026-05-16.
> Its successor `libva-v4l2-request-fourier` tracks the campaign fork's
> git history directly
> ([git.reauktion.de/marfrit/libva-v4l2-request-fourier](https://git.reauktion.de/marfrit/libva-v4l2-request-fourier))
> so iteration sweeps (DEBUG removal, follow-up bugfixes) land in a clean
> linear log, and adds the iter38 multi-device probe that lets a single
> libva session serve rkvdec H.264/HEVC/VP9 + hantro MPEG-2/VP8 without
> needing `LIBVA_V4L2_REQUEST_VIDEO_PATH` overrides.
>
> `libva-v4l2-request-fourier` declares
> `replaces=('libva-v4l2-request-ohm-gl-fix')`, so installing it will
> remove this package automatically. Kept in-tree as historical reference
> for the ohm_gl_fix Phase 6 audit trail.
---
Bootlin's libva-v4l2-request VA-API backend, with hantro-vpu Bootlin's libva-v4l2-request VA-API backend, with hantro-vpu
multi-planar + chromium-149-era stateless H.264 patches developed multi-planar + chromium-149-era stateless H.264 patches developed
in the [ohm_gl_fix campaign](../../../ohm_gl_fix/) Phase 6 Step 1 in the [ohm_gl_fix campaign](../../../ohm_gl_fix/) Phase 6 Step 1
+150
View File
@@ -0,0 +1,150 @@
# Maintainer: Markus Fritsche <mfritsche@reauktion.de>
#
# linux-ampere-fourier — CoolPi GenBook (RK3588) kernel from the
# marfrit-iterated linux-rk3588-marfrit branch (pinned commit).
#
# Baseline carries the marfrit RK3588 delta on top of mainline v7.0-rc3:
# 10 Markus commits (board DTS + Kconfig + suspend/wakeup + bluetooth)
# plus 8 upstream cherry-picks (Shawn Lin's pcie3 phy series, Collabora
# clk/dts/dw-dp fixes, Sebastian Reichel's Rock 5 ITX hdmirx). The 6
# board-relevant patches are scope-tagged in marfrit/kernel-agent under
# patches/{soc,module,board}/ — see fleet/ampere.yaml manifest.
#
# Coexists with the user's other extlinux labels in
# /boot/firmware/extlinux/extlinux.conf; never edits them. Adds a
# managed `linux-ampere-fourier` label (the user sets `default` manually
# after verifying boot).
#
# Bootloader path: /boot/firmware/ (vfat on mmcblk0p1). Kernel +
# initramfs + DTB land there directly. Reverting = boot a different
# extlinux label (e.g. arch_mainline, ubuntu_mainline).
pkgbase=linux-ampere-fourier
pkgname=("$pkgbase" "$pkgbase-headers")
pkgver=7.0rc3.kafr1
pkgrel=1
pkgdesc='CoolPi GenBook kernel (linux-rk3588-marfrit @ f8f3ad9 + RK3588 cherry-picks + GenBook DTS)'
arch=(aarch64)
url='https://git.reauktion.de/marfrit/kernel-agent'
license=(GPL-2.0-only)
makedepends=(
bc cpio gettext kmod libelf pahole perl python tar xz
ccache
uboot-tools dtc
)
options=('!strip')
# Pinned tip of marfrit/linux-rk3588-marfrit. 18 commits ahead of v7.0-rc3:
# 10 by Markus Fritsche (board/SoC/module/Bluetooth/Kconfig)
# 4 by Shawn Lin (phy: rockchip-snps-pcie3 stability series)
# 2 by Cristian Ciocaltea (clk + dw-dp bridge — Collabora track)
# 1 by Sebastian Reichel (Rock 5 ITX hdmirx — not used by ampere)
# 1 by Pedro Alves (CLK_SET_RATE_PARENT VOP2 fix)
_commit=f8f3ad934433bd7e1207d9b0b37e817a692b7ee9
source=(
# Local tarball produced by ./prebuild.sh from a local clone of the
# linux-rk3588-marfrit branch. Not fetched from a URL because the
# boltzmann working clone is shallow (gitea push rejects) and the
# 260MB tarball isn't committed to marfrit-packages. Run prebuild.sh
# before makepkg; see README in this dir.
"linux-rk3588-marfrit-${_commit:0:7}.tar.gz"
'config' # snapshot of running ampere kernel's /proc/config.gz (7.0.0-rc3-ARCH+)
'linux-ampere-fourier.preset'
'extlinux-add.hook'
'extlinux-add.sh'
)
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
# kernelrelease becomes <Makefile-VERSION>.<PATCH>.<SUBLEVEL><EXTRAVERSION><LOCALVERSION>
# i.e. 7.0.0-rc3-ampere-fourier. Module dir + EXTRAVERSION suffix keep
# this disjoint from the hand-managed /boot/firmware/Image-7.0.0-rc3-ARCH+
# that's currently on the host.
_kernver=7.0.0-rc3-ampere-fourier
_srcdir=linux-rk3588-marfrit
prepare() {
cd "${_srcdir}"
echo ":: writing config"
cp "${srcdir}/config" .config
# LOCALVERSION suffix to differentiate from upstream-stock builds.
scripts/config --set-str LOCALVERSION "-ampere-fourier"
scripts/config -d LOCALVERSION_AUTO
echo ":: olddefconfig (accept new symbols sensibly)"
make olddefconfig
make -s kernelrelease > version
echo ":: kernel release: $(<version)"
}
build() {
cd "${_srcdir}"
unset LDFLAGS
# Native build only — no distcc per kernel-agent policy
# (feedback_kernel_agent_no_distcc.md). ccache stays.
export CC="ccache gcc"
export HOSTCC="ccache gcc"
make ${MAKEFLAGS:--j$(nproc)} Image modules dtbs
}
_package() {
pkgdesc='CoolPi GenBook overclocked kernel (ampere-fourier baseline)'
depends=(coreutils kmod mkinitcpio uboot-tools)
optdepends=('linux-firmware: firmware images needed for some devices')
backup=("etc/mkinitcpio.d/${pkgbase}.preset")
cd "${_srcdir}"
local _kver
_kver=$(<version)
# Kernel image into the vfat firmware partition (where extlinux looks).
install -Dm644 arch/arm64/boot/Image \
"${pkgdir}/boot/firmware/Image-ampere-fourier"
# Single DTB for the GenBook target — install directly under
# /boot/firmware/ (no subdir, matches existing host convention).
install -Dm644 arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dtb \
"${pkgdir}/boot/firmware/rk3588-coolpi-cm5-genbook.dtb-ampere-fourier"
ZSTD_CLEVEL=19 make INSTALL_MOD_PATH="${pkgdir}/usr" \
INSTALL_MOD_STRIP=1 modules_install
rm -f "${pkgdir}/usr/lib/modules/${_kver}/"{source,build}
install -Dm644 "${srcdir}/${pkgbase}.preset" \
"${pkgdir}/etc/mkinitcpio.d/${pkgbase}.preset"
install -Dm755 "${srcdir}/extlinux-add.hook" \
"${pkgdir}/usr/share/libalpm/hooks/95-${pkgbase}-extlinux.hook"
install -Dm755 "${srcdir}/extlinux-add.sh" \
"${pkgdir}/usr/share/libalpm/scripts/${pkgbase}-extlinux"
}
_package-headers() {
pkgdesc='Headers and scripts for the linux-ampere-fourier kernel'
depends=(pahole)
cd "${_srcdir}"
local _kver _builddir
_kver=$(<version)
_builddir="${pkgdir}/usr/lib/modules/${_kver}/build"
install -Dt "${_builddir}" -m644 .config Makefile Module.symvers System.map vmlinux version
install -Dt "${_builddir}/kernel" -m644 kernel/Makefile
cp -a scripts "${_builddir}"
install -Dt "${_builddir}/arch/arm64" -m644 arch/arm64/Makefile
cp -a arch/arm64/include "${_builddir}/arch/arm64/"
cp -a include "${_builddir}/"
find . -name 'Kbuild' -exec install -Dm644 {} "${_builddir}/{}" \;
find . -name 'Kconfig*' -exec install -Dm644 {} "${_builddir}/{}" \;
install -d "${pkgdir}/usr/src"
ln -sr "${_builddir}" "${pkgdir}/usr/src/${pkgbase}"
}
eval "package_${pkgbase}() { _package; }"
eval "package_${pkgbase}-headers() { _package-headers; }"
+70
View File
@@ -0,0 +1,70 @@
# linux-ampere-fourier
Kernel package for ampere (CoolPi GenBook RK3588). Baselined on
`marfrit/linux-rk3588-marfrit @ f8f3ad9` (mainline v7.0-rc3 + 18
RK3588-fleet-relevant commits — 10 Markus, 8 upstream cherry-picks).
See `marfrit/kernel-agent/fleet/ampere.yaml` for the manifest +
`marfrit/kernel-agent/patches/{soc,module,board}/...` for the
scope-tagged board patches in the baseline.
## Build
The kernel source isn't on Gitea — boltzmann's working clone is
shallow (Gitea refuses shallow pushes) and a 260MB tarball doesn't
belong in `marfrit-packages`. Stage the source locally from a
clone of the `linux-rk3588-marfrit` branch:
```sh
cd arch/linux-ampere-fourier
./prebuild.sh # produces linux-rk3588-marfrit-f8f3ad9.tar.gz
makepkg -s --noconfirm # native aarch64 build; no distcc
```
`prebuild.sh` looks at `$LINUX_RK3588_MARFRIT_TREE` (default
`~/src/linux-rockchip`) for the kernel working tree. The tip commit
must be reachable in that clone — fetch the `linux-rk3588-marfrit`
branch first if you cloned from elsewhere.
## Build hosts
Native aarch64 only (per kernel-agent `feedback_kernel_agent_no_distcc.md`).
Either ampere itself (8C/2.4GHz, 32GB, native arch) or boltzmann
(Rock 5 ITX+, same uarch). fermi as fallback.
## Install
Adds a managed label to `/boot/firmware/extlinux/extlinux.conf`:
```
label linux-ampere-fourier
menu label linux-ampere-fourier (managed)
kernel /Image-ampere-fourier
initrd /initramfs-ampere-fourier.img
fdt /rk3588-coolpi-cm5-genbook.dtb-ampere-fourier
append <inherited from arch_mainline>
```
Default label is NOT changed. After verifying boot of the managed
label at the u-boot menu, you flip `default` manually. Reverting =
boot a different label (e.g. `arch_mainline`, `ubuntu_mainline`).
## Boot path
ampere uses `/boot/firmware/` (vfat on mmcblk0p1, ~1G), distinct
from fresnel's `/boot/` on root partition. The PKGBUILD installs
Image, initramfs, and DTB directly under `/boot/firmware/`. No
DTB subdir — single board target.
## Open follow-ups (per kernel-agent issue #6)
- **Ask 2** (VP9 enablement on RK3588 rkvdec) — not addressed in this
iteration. Separate session.
- **Ask 3** (AV1 decoder integration) — backend libva work, not kernel.
- Hosting the source tarball publicly so `prebuild.sh` isn't needed —
candidate: Gitea release asset, or `packages.reauktion.de/sources/`.
- Splitting the 12 non-board cherry-pick commits in the baseline
(4 Shawn Lin phy, 2 Cristian Ciocaltea, etc.) into scope-tagged
patches in kernel-agent — currently they ride along inside the
pinned baseline rather than being explicit `includes:` in the
manifest.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,13 @@
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = boot/firmware/Image-ampere-fourier
Target = boot/firmware/rk3588-coolpi-cm5-genbook.dtb-ampere-fourier
Target = boot/firmware/initramfs-ampere-fourier.img
[Action]
Description = Updating extlinux entry for linux-ampere-fourier
When = PostTransaction
Exec = /usr/share/libalpm/scripts/linux-ampere-fourier-extlinux
+62
View File
@@ -0,0 +1,62 @@
#!/bin/sh
# Add / update / remove the linux-ampere-fourier entry in
# /boot/firmware/extlinux/extlinux.conf. Idempotent. Coexists with
# the hand-managed labels in that file; never edits them. Default
# label is NOT touched — user picks at u-boot menu.
#
# ampere boots from a vfat partition (mmcblk0p1) mounted at
# /boot/firmware/, distinct from fresnel's /boot/ on root.
set -eu
CONF="/boot/firmware/extlinux/extlinux.conf"
TAG_BEGIN="# >>> linux-ampere-fourier (managed) >>>"
TAG_END="# <<< linux-ampere-fourier (managed) <<<"
# Copy APPEND from the user's `arch_mainline` label so the managed
# entry inherits the same root= and console= settings the host's
# bootloader already trusts. Falls back to a CoolPi GenBook default
# if no arch_mainline label exists (first-time install on a fresh
# bootloader config).
EXISTING_APPEND=$(awk '
/^[[:space:]]*label[[:space:]]+arch_mainline[[:space:]]*$/ { found=1; next }
found && /^[[:space:]]*append[[:space:]]/ {
sub(/^[[:space:]]*append[[:space:]]+/, "")
print
exit
}
/^[[:space:]]*label[[:space:]]/ { found=0 }
' "$CONF" 2>/dev/null || true)
APPEND="${EXISTING_APPEND:-root=LABEL=arch rw rootwait rootfstype=btrfs rootflags=subvol=@,ssd,discard=async console=ttyS2,1500000 console=tty1 consoleblank=0 loglevel=7 cma=256M coherent_pool=2M}"
ENTRY=$(cat <<EOF
${TAG_BEGIN}
label linux-ampere-fourier
menu label linux-ampere-fourier (managed)
kernel /Image-ampere-fourier
initrd /initramfs-ampere-fourier.img
fdt /rk3588-coolpi-cm5-genbook.dtb-ampere-fourier
append ${APPEND}
${TAG_END}
EOF
)
# Strip any prior managed block, then append fresh
TMP=$(mktemp)
awk -v b="$TAG_BEGIN" -v e="$TAG_END" '
$0==b{skip=1; next}
$0==e{skip=0; next}
!skip{print}
' "$CONF" > "$TMP"
# Post-Remove: kernel files absent → don't re-add the entry
if [ -f "/boot/firmware/Image-ampere-fourier" ] \
&& [ -f "/boot/firmware/rk3588-coolpi-cm5-genbook.dtb-ampere-fourier" ]; then
printf '%s\n' "$ENTRY" >> "$TMP"
echo "linux-ampere-fourier: extlinux entry updated"
else
echo "linux-ampere-fourier: kernel files absent, entry removed"
fi
mv "$TMP" "$CONF"
@@ -0,0 +1,13 @@
# mkinitcpio preset for linux-ampere-fourier
#
# ampere boots from /boot/firmware/ (vfat partition on mmcblk0p1). The
# initramfs lands there too so extlinux can pick it up. Only one PRESET
# because /boot/firmware is ~1G total — no room for a fallback image
# alongside the primary.
ALL_kver="/boot/firmware/Image-ampere-fourier"
ALL_microcode=()
PRESETS=('default')
default_image="/boot/firmware/initramfs-ampere-fourier.img"
+65
View File
@@ -0,0 +1,65 @@
#!/bin/bash
# prebuild — stage the kernel source tarball this PKGBUILD expects.
#
# linux-ampere-fourier's source is a snapshot of marfrit/linux-rk3588-marfrit
# @ f8f3ad9 (260MB), too big to commit to marfrit-packages and currently
# unpushable to Gitea (boltzmann's working clone is shallow; gitea push
# refuses shallow updates). Hosting the tarball outside Gitea would need
# infrastructure setup that's not in scope for the first iteration.
#
# So: produce the tarball locally from the kernel working tree just
# before makepkg runs. Idempotent — if an existing tarball matches the
# expected sha256 we skip the archive step.
#
# Run from this directory: cd arch/linux-ampere-fourier && ./prebuild.sh
# Override the kernel-tree location: LINUX_RK3588_MARFRIT_TREE=/path ./prebuild.sh
#
# Default tree location matches the boltzmann/ampere convention from
# kernel-agent issue #6: $HOME/src/linux-rockchip.
set -euo pipefail
TREE="${LINUX_RK3588_MARFRIT_TREE:-${HOME}/src/linux-rockchip}"
COMMIT=f8f3ad934433bd7e1207d9b0b37e817a692b7ee9
SHA256_EXPECTED=b4eca11e883fe6f7f306d8751c3efa3afed9cc3465c74a3320de1b7204f5f330
HERE="$(cd "$(dirname "$0")" && pwd)"
OUTPUT="${HERE}/linux-rk3588-marfrit-${COMMIT:0:7}.tar.gz"
if [ -f "$OUTPUT" ]; then
have=$(sha256sum "$OUTPUT" | cut -d' ' -f1)
if [ "$have" = "$SHA256_EXPECTED" ]; then
echo "prebuild: $OUTPUT already exists with correct sha256"
exit 0
else
echo "prebuild: existing $OUTPUT sha mismatch (have=$have, want=$SHA256_EXPECTED) — regenerating" >&2
rm -f "$OUTPUT"
fi
fi
if [ ! -d "$TREE/.git" ]; then
echo "prebuild: kernel tree not at $TREE" >&2
echo " set LINUX_RK3588_MARFRIT_TREE=/path/to/linux-rockchip and retry" >&2
exit 2
fi
cd "$TREE"
if ! git cat-file -e "$COMMIT" 2>/dev/null; then
echo "prebuild: commit $COMMIT not found in $TREE" >&2
echo " fetch the linux-rk3588-marfrit branch first:" >&2
echo " git fetch <remote> linux-rk3588-marfrit" >&2
exit 3
fi
echo "prebuild: generating archive from $TREE @ $COMMIT..."
git archive --format=tar.gz --prefix=linux-rk3588-marfrit/ "$COMMIT" -o "$OUTPUT"
# git archive emits a deterministic tar stream but gzip compression may
# vary by version. The sha256 check is informational; warn-don't-fail.
have=$(sha256sum "$OUTPUT" | cut -d' ' -f1)
if [ "$have" != "$SHA256_EXPECTED" ]; then
echo "prebuild: WARNING $OUTPUT sha=$have (canonical=$SHA256_EXPECTED)" >&2
echo " probably a gzip-version difference; tar payload should be identical" >&2
fi
echo "prebuild: wrote $OUTPUT ($(du -h "$OUTPUT" | cut -f1), sha=$have)"
@@ -0,0 +1,356 @@
From a202de1646d4c8f8ee2ebc2e4c100b621975754a Mon Sep 17 00:00:00 2001
In-Reply-To: <20260429195306.239666-1-mfritsche@reauktion.de>
References: <20260429195306.239666-1-mfritsche@reauktion.de>
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Sat, 9 May 2026 16:16:07 +0200
Subject: [PATCH RFC v2] media: videobuf2: add opt-in dma_resv producer fence
helper
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
V4L2 producers historically don't propagate buffer-state-done into
the dmabuf's dma_resv exclusive fence. Userspace consumers that
import V4L2-produced dmabufs and wait on the dmabuf's implicit-sync
fence (poll(POLLIN), DMA_BUF_IOCTL_EXPORT_SYNC_FILE,
EGL_LINUX_DMA_BUF_EXT) currently see either zero fences or a stub
fence from dma_fence_get_stub(). This is correct by accident for the
common DQBUF-then-import case but represents a contract gap that
breaks Wayland compositors importing CAPTURE buffers from a stateless
H.264 decoder under continuous playback on implicit-sync GPU stacks
(observed on RK3566 + hantro VPU + Mali-G52 panfrost; manifests as
green frames -- BT.709 limited-range YUV(0,0,0) -> RGB(0,77,0) -- when
the GPU samples the dmabuf before the producer's decode completes).
Add an opt-in API gated by both a per-driver runtime flag
(vb2_queue::supports_release_fences) and a Kconfig
(CONFIG_VIDEOBUF2_RELEASE_FENCES, default n) that lets producers
populate a real dma_resv exclusive write fence on the dmabufs they
export. Drivers call vb2_buffer_attach_release_fence(vb) at a
finite-time-fenced point in their pipeline (typically m2m
device_run, just before the HW kick); vb2_buffer_done() signals and
puts the fence as part of its state transition.
The publish and signal paths are wrapped in
dma_fence_begin_signalling() / dma_fence_end_signalling() so
PROVE_LOCKING can validate that nothing taken in those critical
sections deadlocks against the signal path. dma_resv_lock is
sleepable but not taken on the signal path, so taking it inside the
publish critical section is safe under lockdep.
Skips planes whose vb2_plane.dbuf is NULL -- buffers never exported
via VIDIOC_EXPBUF (or imported via V4L2_MEMORY_DMABUF) have no
dmabuf for userspace to wait on.
Drivers that don't opt in pay nothing: the helper is a no-op stub
when CONFIG_VIDEOBUF2_RELEASE_FENCES=n, and an early-return check
of supports_release_fences when =y but the flag is unset.
Validated on RK3566 PineTab2 with PROVE_LOCKING enabled: 30s of
bbb_1080p30 H.264 stateless decode + zero-copy panfrost EGL import
via dmabuf-wayland (mpv 0.41 + KWin 6.6.4 + Mesa panfrost 26.0.5)
produces 31,816 dma_fence init/signal pairs across 5,724 vb2 buffer
cycles with zero lockdep splats from videobuf2 / dma_resv code paths.
Subsequent patches in this series opt the hantro and rockchip-rga
drivers in.
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Christian König <christian.koenig@amd.com>
Cc: Nicolas Dufresne <nicolas@ndufresne.ca>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Tomasz Figa <tfiga@chromium.org>
Cc: linux-media@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linaro-mm-sig@lists.linaro.org
Signed-off-by: Markus Fritsche <mfritsche@reauktion.de>
---
drivers/media/common/videobuf2/Kconfig | 29 ++++
.../media/common/videobuf2/videobuf2-core.c | 135 ++++++++++++++++++
include/media/videobuf2-core.h | 51 +++++++
3 files changed, 215 insertions(+)
diff --git a/drivers/media/common/videobuf2/Kconfig b/drivers/media/common/videobuf2/Kconfig
index d2223a12c..bbfa26984 100644
--- a/drivers/media/common/videobuf2/Kconfig
+++ b/drivers/media/common/videobuf2/Kconfig
@@ -30,3 +30,32 @@ config VIDEOBUF2_DMA_SG
config VIDEOBUF2_DVB
tristate
select VIDEOBUF2_CORE
+
+config VIDEOBUF2_RELEASE_FENCES
+ bool "videobuf2: opt-in dma_resv producer fences for V4L2 dmabuf exports"
+ depends on VIDEOBUF2_CORE
+ depends on DMA_SHARED_BUFFER
+ default n
+ help
+ Enables an opt-in API that lets vb2 producers populate a dma_resv
+ exclusive write fence on the dmabufs they export to userspace.
+ The fence is signalled when the buffer transitions to
+ VB2_BUF_STATE_DONE.
+
+ This gives userspace consumers that import V4L2-produced dmabufs
+ and wait on the dmabuf's implicit-sync fence (poll(POLLIN),
+ DMA_BUF_IOCTL_EXPORT_SYNC_FILE, EGL_LINUX_DMA_BUF_EXT) a real
+ producer fence to wait on, instead of a stub fence from
+ dma_fence_get_stub() that the dma_buf core substitutes when
+ dma_resv is empty.
+
+ Drivers individually opt in by setting
+ vb2_queue::supports_release_fences = true and calling
+ vb2_buffer_attach_release_fence() at the right point in their
+ pipeline (typically m2m device_run, just before HW kick).
+
+ Distributors leave this off unless targeting Wayland/EGL
+ consumers of V4L2 stateless decoder output on
+ implicit-sync-only GPU stacks (e.g. mainline panfrost).
+
+ If unsure, say N.
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index adf668b21..85d7fddbd 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -26,6 +26,12 @@
#include <linux/freezer.h>
#include <linux/kthread.h>
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+#include <linux/dma-fence.h>
+#include <linux/dma-resv.h>
+#include <linux/dma-buf.h>
+#endif
+
#include <media/videobuf2-core.h>
#include <media/v4l2-mc.h>
@@ -1173,6 +1179,120 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
}
EXPORT_SYMBOL_GPL(vb2_plane_cookie);
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+/*
+ * dma_resv release-fence integration.
+ *
+ * Optional, opt-in path that lets producers publish a real
+ * dma_fence on their CAPTURE-side dmabufs so userspace consumers
+ * (compositors, EGL importers) get spec-clean implicit-sync
+ * semantics instead of the dma_buf core's stub fence. Drivers
+ * call vb2_buffer_attach_release_fence() at a finite-time-fenced
+ * point (typically m2m device_run) and the fence is signalled by
+ * vb2_buffer_done(). Gated at runtime by
+ * vb2_queue::supports_release_fences and at compile time by
+ * CONFIG_VIDEOBUF2_RELEASE_FENCES.
+ */
+
+static const char *vb2_dma_resv_get_driver_name(struct dma_fence *fence)
+{
+ return "videobuf2";
+}
+
+static const char *vb2_dma_resv_get_timeline_name(struct dma_fence *fence)
+{
+ return "vb2-release-fence";
+}
+
+static const struct dma_fence_ops vb2_dma_resv_fence_ops = {
+ .get_driver_name = vb2_dma_resv_get_driver_name,
+ .get_timeline_name = vb2_dma_resv_get_timeline_name,
+};
+
+int vb2_buffer_attach_release_fence(struct vb2_buffer *vb)
+{
+ struct vb2_queue *q = vb->vb2_queue;
+ struct dma_fence *fence;
+ unsigned int plane;
+ bool cookie;
+
+ if (!q->supports_release_fences)
+ return 0;
+
+ if (WARN_ON(vb->release_fence))
+ return -EINVAL;
+
+ fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+ if (!fence)
+ return -ENOMEM;
+
+ dma_fence_init(fence, &vb2_dma_resv_fence_ops, &q->dma_resv_fence_lock,
+ q->dma_resv_fence_context,
+ atomic64_inc_return(&q->dma_resv_fence_seqno));
+
+ /*
+ * Annotate the publish-side critical section. Per
+ * Documentation/driver-api/dma-buf.rst, lockdep validates
+ * that nothing taken in this region can deadlock against
+ * the signal path in vb2_buffer_signal_release_fence().
+ * dma_resv_lock is sleepable but is not taken on the signal
+ * path, so taking it inside the critical section is safe.
+ */
+ cookie = dma_fence_begin_signalling();
+ for (plane = 0; plane < vb->num_planes; plane++) {
+ struct dma_buf *dbuf = vb->planes[plane].dbuf;
+
+ if (!dbuf)
+ continue;
+
+ dma_resv_lock(dbuf->resv, NULL);
+ dma_resv_add_fence(dbuf->resv, fence, DMA_RESV_USAGE_WRITE);
+ dma_resv_unlock(dbuf->resv);
+ }
+ dma_fence_end_signalling(cookie);
+
+ /* One reference for the eventual signal in vb2_buffer_done. */
+ vb->release_fence = dma_fence_get(fence);
+
+ /* The dma_resv held its own reference per plane. Drop ours. */
+ dma_fence_put(fence);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_buffer_attach_release_fence);
+
+static void vb2_buffer_signal_release_fence(struct vb2_buffer *vb,
+ enum vb2_buffer_state state)
+{
+ struct dma_fence *fence = vb->release_fence;
+ bool cookie;
+
+ if (!fence)
+ return;
+
+ cookie = dma_fence_begin_signalling();
+ if (state == VB2_BUF_STATE_ERROR)
+ dma_fence_set_error(fence, -EIO);
+ dma_fence_signal(fence);
+ dma_fence_end_signalling(cookie);
+
+ dma_fence_put(fence);
+ vb->release_fence = NULL;
+}
+#else /* !CONFIG_VIDEOBUF2_RELEASE_FENCES */
+
+int vb2_buffer_attach_release_fence(struct vb2_buffer *vb)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_buffer_attach_release_fence);
+
+static inline void vb2_buffer_signal_release_fence(struct vb2_buffer *vb,
+ enum vb2_buffer_state state)
+{
+}
+#endif /* CONFIG_VIDEOBUF2_RELEASE_FENCES */
+
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
{
struct vb2_queue *q = vb->vb2_queue;
@@ -1199,6 +1319,9 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
if (state != VB2_BUF_STATE_QUEUED)
__vb2_buf_mem_finish(vb);
+ if (state != VB2_BUF_STATE_QUEUED)
+ vb2_buffer_signal_release_fence(vb, state);
+
spin_lock_irqsave(&q->done_lock, flags);
if (state == VB2_BUF_STATE_QUEUED) {
vb->state = VB2_BUF_STATE_QUEUED;
@@ -2651,6 +2774,18 @@ int vb2_core_queue_init(struct vb2_queue *q)
mutex_init(&q->mmap_lock);
init_waitqueue_head(&q->done_wq);
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+ /*
+ * Per-queue dma_resv release-fence context. Drivers that
+ * opt in via supports_release_fences and call
+ * vb2_buffer_attach_release_fence() use these to allocate
+ * fences on a single per-queue timeline.
+ */
+ q->dma_resv_fence_context = dma_fence_context_alloc(1);
+ atomic64_set(&q->dma_resv_fence_seqno, 0);
+ spin_lock_init(&q->dma_resv_fence_lock);
+#endif
+
q->memory = VB2_MEMORY_UNKNOWN;
if (q->buf_struct_size == 0)
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4424d481d..766ff2194 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -288,6 +288,16 @@ struct vb2_buffer {
unsigned int skip_cache_sync_on_finish:1;
struct vb2_plane planes[VB2_MAX_PLANES];
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+ /*
+ * Producer release fence published on each plane's
+ * dmabuf->resv when the driver opts in via
+ * vb2_buffer_attach_release_fence(). Signalled and put by
+ * vb2_buffer_done() on transition to DONE/ERROR. NULL when
+ * the driver did not opt in for this buffer.
+ */
+ struct dma_fence *release_fence;
+#endif
struct list_head queued_entry;
struct list_head done_entry;
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -648,6 +658,19 @@ struct vb2_queue {
spinlock_t done_lock;
wait_queue_head_t done_wq;
+#ifdef CONFIG_VIDEOBUF2_RELEASE_FENCES
+ /*
+ * dma_resv release-fence context. Drivers that set
+ * supports_release_fences and call
+ * vb2_buffer_attach_release_fence() use these to allocate
+ * fences on a per-queue timeline.
+ */
+ u64 dma_resv_fence_context;
+ atomic64_t dma_resv_fence_seqno;
+ spinlock_t dma_resv_fence_lock;
+#endif
+
+ unsigned int supports_release_fences:1;
unsigned int streaming:1;
unsigned int start_streaming_called:1;
unsigned int error:1;
@@ -735,6 +758,34 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no);
*/
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
+/**
+ * vb2_buffer_attach_release_fence() - opt-in dma_resv release fence.
+ * @vb: the buffer being committed to the producer.
+ *
+ * Drivers that have set vb2_queue::supports_release_fences may call
+ * this from any sleepable context where they have committed to
+ * running the operation in finite time -- typically m2m
+ * device_run(), just before the HW kick. The helper allocates a
+ * dma_fence on the queue's per-queue timeline, attaches it as
+ * DMA_RESV_USAGE_WRITE on each plane's dmabuf->resv, and stashes
+ * it in vb->release_fence. vb2_buffer_done() signals and puts the
+ * fence as part of the buffer's state transition.
+ *
+ * Skips planes whose vb2_plane.dbuf is NULL -- buffers never
+ * exported via VIDIOC_EXPBUF (or imported via V4L2_MEMORY_DMABUF)
+ * have no dmabuf for userspace to wait on.
+ *
+ * No-op when vb2_queue::supports_release_fences is not set
+ * (regardless of CONFIG_VIDEOBUF2_RELEASE_FENCES). When
+ * CONFIG_VIDEOBUF2_RELEASE_FENCES=n, this is a stub that returns 0.
+ *
+ * Returns 0 on success or when the no-op stub is in effect,
+ * negative errno on allocation failure when fence publishing was
+ * attempted. Best-effort: drivers should ignore the return value
+ * unless they want diagnostics.
+ */
+int vb2_buffer_attach_release_fence(struct vb2_buffer *vb);
+
/**
* vb2_discard_done() - discard all buffers marked as DONE.
* @q: pointer to &struct vb2_queue with videobuf2 queue.
--
2.53.0
@@ -0,0 +1,95 @@
From 1844c263bde8dd244d7db46f8c508e7c70da459c Mon Sep 17 00:00:00 2001
In-Reply-To: <20260429195306.239666-1-mfritsche@reauktion.de>
References: <20260429195306.239666-1-mfritsche@reauktion.de>
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Sat, 9 May 2026 16:24:01 +0200
Subject: [PATCH RFC v2] media: hantro: attach dma_resv release fence at
device_run
Opt the hantro driver into the new vb2 release-fence helper so its
CAPTURE-side dmabufs carry a real producer fence that wayland
compositors and other implicit-sync consumers can wait on, instead
of the dma_buf core's stub fence.
Attach point is m2m device_run, immediately after
v4l2_m2m_buf_copy_metadata() and before ctx->codec_ops->run().
Per Nicolas Dufresne's v1 review (lore.kernel.org/linux-media/
3d8deeb15581b754e4c061d4c4a13657aa08bc3c.camel@ndufresne.ca/),
this satisfies the dma_fence finite-time contract: the m2m core
has committed to running the job by this point, codec_ops->run
either kicks the HW (decode-complete signals the fence via
vb2_buffer_done) or fails immediately (job_finish with
VB2_BUF_STATE_ERROR signals with -EIO). PM and clocks are already
up by this point, so no allocation context restrictions.
The CAPTURE queue is opted in with supports_release_fences=true at
queue_init.
Userspace consumers that import hantro CAPTURE dmabufs and wait on
their implicit-sync fence (Wayland zwp_linux_dmabuf_v1 +
panfrost EGL_LINUX_DMA_BUF_EXT) now wait on a real fence
representing the producer's actual completion, fixing green-frame
corruption observed on RK3566 PineTab2 + Mali-G52 panfrost (the
GPU was sampling zero pages because the dmabuf's implicit fence
was the dma_buf core's pre-signalled stub).
Validated end-to-end on PineTab2 (RK3566 / hantro G1 / Mali-G52
mainline panfrost): 30s of bbb_1080p30 H.264 stateless decode +
zero-copy panfrost EGL import via dmabuf-wayland (mpv 0.41 +
KWin 6.6.4 + Mesa panfrost 26.0.5) renders correctly with no
green-frame corruption and no PROVE_LOCKING splats.
Cc: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Nicolas Dufresne <nicolas@ndufresne.ca>
Cc: linux-media@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
Signed-off-by: Markus Fritsche <mfritsche@reauktion.de>
---
.../media/platform/verisilicon/hantro_drv.c | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 2e81877f6..6a66c47ed 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -186,6 +186,22 @@ static void device_run(void *priv)
v4l2_m2m_buf_copy_metadata(src, dst);
+ /*
+ * Attach a producer fence on the CAPTURE-side dmabuf so userspace
+ * importers (e.g. Wayland compositors) get spec-clean implicit-sync
+ * semantics. Called from device_run rather than buf_queue: the
+ * dma_fence finite-time contract requires that once a fence is
+ * published, the producer must signal it in finite time. By the
+ * time we reach device_run, the m2m core has committed to running
+ * this job, and the next hop (codec_ops->run) either kicks the HW
+ * (decode-complete signals the fence via vb2_buffer_done) or
+ * fails immediately (job_finish with VB2_BUF_STATE_ERROR signals
+ * the fence with -EIO). Either path resolves the fence in finite
+ * time. Best-effort: a NOMEM here means we lose implicit-sync
+ * precision for this frame, no functional regression.
+ */
+ (void)vb2_buffer_attach_release_fence(&dst->vb2_buf);
+
if (ctx->codec_ops->run(ctx))
goto err_cancel_job;
@@ -249,6 +265,13 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
dst_vq->lock = &ctx->dev->vpu_mutex;
dst_vq->dev = ctx->dev->v4l2_dev.dev;
+ /*
+ * Opt the CAPTURE queue into vb2 release-fence publishing.
+ * No-op unless CONFIG_VIDEOBUF2_RELEASE_FENCES=y; runtime cost
+ * is one extra fence allocation + dma_resv update per device_run.
+ */
+ dst_vq->supports_release_fences = true;
+
return vb2_queue_init(dst_vq);
}
--
2.53.0
@@ -0,0 +1,117 @@
From 2c63a63bf65739763051dc4ce7ce2ffaf2d514c4 Mon Sep 17 00:00:00 2001
In-Reply-To: <20260429195306.239666-1-mfritsche@reauktion.de>
References: <20260429195306.239666-1-mfritsche@reauktion.de>
From: Markus Fritsche <mfritsche@reauktion.de>
Date: Sat, 9 May 2026 16:50:51 +0200
Subject: [PATCH RFC v2] media: rockchip-rga: attach dma_resv release fence at
device_run
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Opt the rockchip-rga driver into the new vb2 release-fence helper.
Same shape as the hantro patch: attach a producer fence on the
CAPTURE-side dmabuf at m2m device_run, signalled by
vb2_buffer_done() when RGA completes the m2m operation.
Differs from hantro in one mechanical detail: rga's device_run
wraps the entire body in spin_lock_irqsave(&rga->ctrl_lock). Our
helper calls dma_resv_lock(), which is sleepable, so the
buffer-fetch + fence-attach sequence has to run above the spinlock.
Restructure device_run so:
- v4l2_m2m_next_src_buf / next_dst_buf,
- src->sequence increment,
- vb2_buffer_attach_release_fence(&dst->vb2_buf)
run before spin_lock_irqsave; only the rga->curr assignment and
rga_hw_start() (the actual HW kick) remain inside the spinlock.
This is safe under the m2m-job ownership model: by the time
device_run is called, the m2m core has selected this context and
serializes one device_run per context, so v4l2_m2m_next_*_buf
returns stable pointers until the corresponding *_buf_remove in
rga_isr. ctrl_lock was previously protecting per-device state
(rga->curr) and the HW register access, neither of which depends on
the buffer-fetch happening inside the lock.
The CAPTURE queue is opted in with supports_release_fences=true at
queue_init.
Userspace consumers of RGA-produced dmabufs (image-processing
pipelines, screen-rotation servers, gstreamer flows on Rockchip
boards) get spec-clean implicit-sync semantics, matching what
hantro does in the previous patch in this series.
Sven Püschel's ongoing "media: platform: rga: Add RGA3 support"
v5 series (linux-rockchip 2026-04-28) restructures rga.c
substantially. If that lands first, the device_run restructure
here will need a rebase against the new shape; the locking story
itself is invariant.
Cc: Jacob Chen <jacob-chen@iotwrt.com>
Cc: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
Cc: Sven Püschel <s.pueschel@pengutronix.de>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: linux-media@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
Signed-off-by: Markus Fritsche <mfritsche@reauktion.de>
---
drivers/media/platform/rockchip/rga/rga.c | 27 +++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index fea63b94c..03030c7ea 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -38,15 +38,28 @@ static void device_run(void *prv)
struct vb2_v4l2_buffer *src, *dst;
unsigned long flags;
- spin_lock_irqsave(&rga->ctrl_lock, flags);
-
- rga->curr = ctx;
-
+ /*
+ * Fetch the next-job buffers and (best-effort) attach a producer
+ * fence on CAPTURE before taking ctrl_lock below.
+ * vb2_buffer_attach_release_fence() takes dma_resv_lock, which is
+ * sleepable; ctrl_lock is taken with spin_lock_irqsave so any
+ * sleepable call must happen above it. Buffer ownership is
+ * already committed at this point: the m2m core has selected
+ * this context for device_run and serializes one device_run per
+ * context, so v4l2_m2m_next_*_buf returns stable pointers until
+ * the corresponding *_buf_remove in rga_isr.
+ */
src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
src->sequence = ctx->osequence++;
dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ (void)vb2_buffer_attach_release_fence(&dst->vb2_buf);
+
+ spin_lock_irqsave(&rga->ctrl_lock, flags);
+
+ rga->curr = ctx;
+
rga_hw_start(rga, vb_to_rga(src), vb_to_rga(dst));
spin_unlock_irqrestore(&rga->ctrl_lock, flags);
@@ -123,6 +136,12 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
dst_vq->lock = &ctx->rga->mutex;
dst_vq->dev = ctx->rga->v4l2_dev.dev;
+ /*
+ * Opt the CAPTURE queue into vb2 release-fence publishing.
+ * Compile-time gated by CONFIG_VIDEOBUF2_RELEASE_FENCES.
+ */
+ dst_vq->supports_release_fences = true;
+
return vb2_queue_init(dst_vq);
}
--
2.53.0
+8 -3
View File
@@ -10,8 +10,8 @@
pkgbase=linux-fresnel-fourier pkgbase=linux-fresnel-fourier
pkgname=("$pkgbase" "$pkgbase-headers") pkgname=("$pkgbase" "$pkgbase-headers")
pkgver=7.0 pkgver=7.0
pkgrel=1 pkgrel=14
pkgdesc='Pinebook Pro kernel (mmind/linux-rockchip v7.0 + OC OPP + PBP DTS tweaks)' pkgdesc='Pinebook Pro kernel (mmind/linux-rockchip v7.0 + OC OPP + PBP DTS tweaks + vb2_dma_resv RFC v2)'
arch=(aarch64) arch=(aarch64)
url='https://git.reauktion.de/marfrit/kernel-agent' url='https://git.reauktion.de/marfrit/kernel-agent'
license=(GPL-2.0-only) license=(GPL-2.0-only)
@@ -23,15 +23,20 @@ makedepends=(
options=('!strip') options=('!strip')
source=( source=(
"https://git.kernel.org/torvalds/t/linux-${pkgver}.tar.gz" "https://git.kernel.org/torvalds/t/linux-${pkgver}.tar.gz"
# board/pinebook-pro
'0001-arm64-dts-rk3399-pinebook-pro-add-OC-OPP-tables-1704-2184.patch' '0001-arm64-dts-rk3399-pinebook-pro-add-OC-OPP-tables-1704-2184.patch'
'0002-arm64-dts-rk3399-pinebook-pro-enable-hdmi-sound.patch' '0002-arm64-dts-rk3399-pinebook-pro-enable-hdmi-sound.patch'
'0003-arm64-dts-rk3399-pinebook-pro-spi1-max-freq-10MHz.patch' '0003-arm64-dts-rk3399-pinebook-pro-spi1-max-freq-10MHz.patch'
# subsystem/media/videobuf2/dma-resv-release-fence (RFC v2, in kernel-agent)
'0004-media-videobuf2-add-opt-in-dma_resv-producer-fence-h.patch'
'0005-media-hantro-attach-dma_resv-release-fence-at-device.patch'
'0006-media-rockchip-rga-attach-dma_resv-release-fence-at-.patch'
'config' # snapshot of fresnel /usr/lib/modules/6.19.10-1-eos-arm/build/.config 'config' # snapshot of fresnel /usr/lib/modules/6.19.10-1-eos-arm/build/.config
'linux-fresnel-fourier.preset' 'linux-fresnel-fourier.preset'
'extlinux-add.hook' 'extlinux-add.hook'
'extlinux-add.sh' 'extlinux-add.sh'
) )
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP') sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')
_kernver=${pkgver}.0-fresnel-fourier _kernver=${pkgver}.0-fresnel-fourier
_srcdir=linux-${pkgver} _srcdir=linux-${pkgver}
+6 -3
View File
@@ -3,15 +3,18 @@
# Source of truth: git.reauktion.de/marfrit/lmcp # Source of truth: git.reauktion.de/marfrit/lmcp
pkgname=lmcp pkgname=lmcp
pkgver=0.5.4 pkgver=1.1.1
pkgrel=1 pkgrel=1
pkgdesc="Lightweight MCP (Model Context Protocol) server in pure Lua" pkgdesc="Lightweight MCP (Model Context Protocol) server in pure Lua"
arch=('any') arch=('any')
url="https://git.reauktion.de/marfrit/lmcp" url="https://git.reauktion.de/marfrit/lmcp"
license=('MIT') license=('MIT')
depends=('lua' 'lua-socket') depends=('lua' 'lua-socket')
source=("${pkgname}-${pkgver}.tar.gz::https://git.reauktion.de/marfrit/lmcp/archive/v${pkgver}.tar.gz") # The _tag back-translation handles both clean releases (no '_') and
sha256sums=('af72b8c1d88255456b75d2c53cd5c451a8923417e5498ef31858539397e09caf') # pre-release pkgvers (e.g. 1.2.0_rc1 → v1.2.0-rc1).
_tag="v${pkgver//_/-}"
source=("${pkgname}-${pkgver}.tar.gz::https://git.reauktion.de/marfrit/lmcp/archive/${_tag}.tar.gz")
sha256sums=('80c2e815aa61a2d3baab051c51cd247bdefa9dd03d72c4867b99c49b6eae9cb9')
package() { package() {
cd "${pkgname}" cd "${pkgname}"
+9 -9
View File
@@ -21,14 +21,14 @@
# pkgbase stays as qt6-base so $_pkgfn (= ${pkgbase/6-/} = "qtbase") # pkgbase stays as qt6-base so $_pkgfn (= ${pkgbase/6-/} = "qtbase")
# resolves correctly. The "-fourier" suffix lives only in the # resolves correctly. The "-fourier" suffix lives only in the
# directory name and the commit history; epoch=1 gives our local # directory name and the commit history; epoch=1 gives our local
# build strict precedence over upstream pkgrel=2 until upstream lands # build strict precedence over upstream pkgrel=N until upstream lands
# the GL_R8/ES3 fix and we can drop the epoch. # the GL_R8/ES3 fix and we can drop the epoch.
pkgbase=qt6-base pkgbase=qt6-base
pkgname=(qt6-base-fourier pkgname=(qt6-base-fourier
qt6-xcb-private-headers-fourier) qt6-xcb-private-headers-fourier)
_pkgver=6.11.0 _pkgver=6.11.1
pkgver=${_pkgver/-/} pkgver=${_pkgver/-/}
pkgrel=3 pkgrel=1
epoch=1 epoch=1
arch=(aarch64 x86_64) arch=(aarch64 x86_64)
url='https://www.qt.io' url='https://www.qt.io'
@@ -42,7 +42,6 @@ depends=(brotli
double-conversion double-conversion
fontconfig fontconfig
freetype2 freetype2
gcc-libs
glib2 glib2
glibc glibc
harfbuzz harfbuzz
@@ -51,6 +50,7 @@ depends=(brotli
libb2 libb2
libcups libcups
libdrm libdrm
libgcc
libgl libgl
libice libice
libinput libinput
@@ -58,6 +58,7 @@ depends=(brotli
libpng libpng
libproxy libproxy
libsm libsm
libstdc++
liburing liburing
libx11 libx11
libxcb libxcb
@@ -115,7 +116,7 @@ source=(git+https://code.qt.io/qt/$_pkgfn#tag=v$_pkgver
0001-qopengltextureglyphcache-pick-GL_R8-on-ES3.patch 0001-qopengltextureglyphcache-pick-GL_R8-on-ES3.patch
0002-qrhigles2-RED_OR_ALPHA8-pick-GL_R8-on-ES3.patch 0002-qrhigles2-RED_OR_ALPHA8-pick-GL_R8-on-ES3.patch
0003-qopengltextureuploader-pick-GL_R8-on-ES3.patch) 0003-qopengltextureuploader-pick-GL_R8-on-ES3.patch)
sha256sums=('2223c075e95d86f8dbf6395b025a74d996c418f094453c903290e3c2663fbed2' sha256sums=('2eafe504fae873d20f206b5661e2e10506879455cb2d370f42c5bb72ccf7a8a1'
'5411edbe215c24b30448fac69bd0ba7c882f545e8cf05027b2b6e2227abc5e78' '5411edbe215c24b30448fac69bd0ba7c882f545e8cf05027b2b6e2227abc5e78'
'4b93f6a79039e676a56f9d6990a324a64a36f143916065973ded89adc621e094' '4b93f6a79039e676a56f9d6990a324a64a36f143916065973ded89adc621e094'
'SKIP' 'SKIP'
@@ -126,9 +127,8 @@ prepare() {
patch -d $_pkgfn -p1 < qt6-base-cflags.patch # Use system CFLAGS patch -d $_pkgfn -p1 < qt6-base-cflags.patch # Use system CFLAGS
patch -d $_pkgfn -p1 < qt6-base-nostrip.patch # Don't strip binaries with qmake patch -d $_pkgfn -p1 < qt6-base-nostrip.patch # Don't strip binaries with qmake
# cherry-pick needs git author identity; git-cli refuses without it. # 8b54513cdcf6 (qdbus crash fix) cherry-pick removed: landed upstream
git -C $_pkgfn -c user.email=fourier@build -c user.name='qt6-base-fourier build' \ # in 6.11.1. Re-add if qdbus regressions re-surface.
cherry-pick -n 8b54513cdcf62047376a5d27d784ad68a8f235bf # Fix qdbus crashes
# qt6-base-fourier — three small runtime-checks that pick GL_R8 over # qt6-base-fourier — three small runtime-checks that pick GL_R8 over
# GL_ALPHA when the live GL context is ES 3 or newer. See the # GL_ALPHA when the live GL context is ES 3 or newer. See the
@@ -165,7 +165,7 @@ build() {
-DFEATURE_system_sqlite=ON \ -DFEATURE_system_sqlite=ON \
-DFEATURE_system_xcb_xinput=ON \ -DFEATURE_system_xcb_xinput=ON \
-DFEATURE_no_direct_extern_access=$_no_direct_extern_access \ -DFEATURE_no_direct_extern_access=$_no_direct_extern_access \
-DFEATURE_sql_ibase=OFF \ -DFEATURE_mimetype_database=OFF \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \ -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
-DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_MESSAGE_LOG_LEVEL=STATUS
cmake --build build cmake --build build
+4 -3
View File
@@ -7,9 +7,10 @@
# package (Architecture: all, depends on lua + lua-socket). # package (Architecture: all, depends on lua + lua-socket).
set -euo pipefail set -euo pipefail
PKGVER=0.5.4 PKGVER=1.1.1
UPSTREAM_TAG=v1.1.1
PKGREL=1 PKGREL=1
LMCP_TARBALL_SHA256=af72b8c1d88255456b75d2c53cd5c451a8923417e5498ef31858539397e09caf LMCP_TARBALL_SHA256=80c2e815aa61a2d3baab051c51cd247bdefa9dd03d72c4867b99c49b6eae9cb9
HERE=$(dirname "$(readlink -f "$0")") HERE=$(dirname "$(readlink -f "$0")")
# Reproducible build: pin all file mtimes + ar member timestamps to a fixed # Reproducible build: pin all file mtimes + ar member timestamps to a fixed
@@ -22,7 +23,7 @@ work=$(mktemp -d)
trap "rm -rf $work" EXIT trap "rm -rf $work" EXIT
cd "$work" cd "$work"
curl -sSLfo lmcp.tar.gz "https://git.reauktion.de/marfrit/lmcp/archive/v${PKGVER}.tar.gz" curl -sSLfo lmcp.tar.gz "https://git.reauktion.de/marfrit/lmcp/archive/${UPSTREAM_TAG}.tar.gz"
echo "$LMCP_TARBALL_SHA256 lmcp.tar.gz" | sha256sum -c echo "$LMCP_TARBALL_SHA256 lmcp.tar.gz" | sha256sum -c
tar xzf lmcp.tar.gz tar xzf lmcp.tar.gz
+59
View File
@@ -1,3 +1,62 @@
lmcp (1.1.1-1) bookworm trixie; urgency=medium
* Bug fix: omit empty inputSchema.properties at tool registration.
The json.lua empty-table-as-array gotcha (same one that bit
`ping` in v1.0.0-rc1) was re-surfacing on tool inputSchemas
declared with `properties = {}` — spec-strict MCP clients (Zod)
rejected the tools/list with "expected: record, received: array".
lmcp:tool() now normalises empty properties tables by dropping
the key entirely (JSON Schema permits omitting `properties` on
`type:object`, meaning "any object — no constraints").
Discovered live on a hertz-tools deployment where two custom
no-arg tools (lxc_list, network_status) tripped the Zod check
and caused Claude Code to mark the entire MCP endpoint as
disconnected.
-- Markus Fritsche <mfritsche@reauktion.de> Mon, 18 May 2026 00:55:00 +0000
lmcp (1.1.0-1) bookworm trixie; urgency=medium
* Concurrent handler dispatch (closes #20): tool handlers run in
cooperative coroutines. server.lua:run()'s sleep_ms yields to
the event loop instead of blocking. Slow shell commands no
longer serialise other requests — fast ping during a slow
`sleep N` returns in ~10ms (was ~N seconds).
* Progress + cancellation notifications (closes #11): tool
handler ctx gains progress(p, total?, message?) and cancelled().
Client→server notifications/cancelled flips a flag the running
handler sees within ~420ms (poll interval capped when ctx
present). Cancelled requests get a JSON-RPC -32800 error
response (spec wording is "SHOULD NOT respond" but the practical
UX wins; see upstream issue for the FD-inheritance trade-off).
* Windows MSI build sync (closes #18): windows/sync.sh script
refreshes windows/pkg/{lmcp,server,json}.lua from root before
WiX is invoked. Closes the drift trap that left the MSI ~6
months behind master in April 2026.
* Zero handler source-code changes; all existing tools (shell,
fetch, web_search, hub remote_*) benefit from concurrency and
auto-cancellation transparently via the run() helper.
-- Markus Fritsche <mfritsche@reauktion.de> Sun, 17 May 2026 19:45:00 +0000
lmcp (1.0.0~rc1-1) bookworm trixie; urgency=medium
* Full MCP 2025-06-18 surface (release candidate). Closes 14
upstream issues. New primitives: Resources, Prompts, Completion,
Logging, Sampling, Roots, fetch, web_search. Protocol: cursor
pagination, structuredContent, _meta passthrough, tool annotations
(readOnlyHint/destructiveHint/idempotentHint/openWorldHint).
Transports: stdio (LMCP_TRANSPORT=stdio) for Claude Desktop / IDE
clients; full Streamable HTTP rewrite with select()-based event
loop, sessions (Mcp-Session-Id), persistent SSE, server-initiated
requests, heartbeat, DELETE.
* json.lua: UTF-16 surrogate-pair combination + json.empty_object
sentinel for spec-correct {} emission (fixes ping's result:[]
bug).
* Backwards compatible with all existing sessionless-POST clients.
-- Markus Fritsche <mfritsche@reauktion.de> Sun, 17 May 2026 17:25:00 +0000
lmcp (0.5.4-1) bookworm trixie; urgency=medium lmcp (0.5.4-1) bookworm trixie; urgency=medium
* Ship examples/lmcp.service systemd unit template alongside the * Ship examples/lmcp.service systemd unit template alongside the