Skip to content

audio: kpb: make KPB service usable from user space - #11425

Open
serhiy-katsyuba-intel wants to merge 3 commits into
thesofproject:mainfrom
serhiy-katsyuba-intel:userspace_kpb_service
Open

serhiy-katsyuba-intel wants to merge 3 commits into
thesofproject:mainfrom
serhiy-katsyuba-intel:userspace_kpb_service

Conversation

@serhiy-katsyuba-intel

Copy link
Copy Markdown
Contributor

Extend the KPB service to support, in addition to the kernel-only notifier interface, the client queue (CONFIG_KPB_CLI_Q), which can also be used from user space.

Replace the k_queue with a statically defined k_msgq that carries struct kpb_client by value, and replace kpb_notifier_init() and kpb_notifier_schedule() with a single kpb_notifier_schedule(id, drain_req) syscall taking only scalar arguments. No pointers are passed from user space to the kernel.

As before, only a single KPB instance is supported.

With the client queue, draining setup runs in the client queue thread instead of the LL thread, so lock the scheduler around kpb_init_draining() to keep kpb_copy() from preempting it. The thread is pinned to the KPB core, so this is sufficient.

Extend the KPB service to support, in addition to the kernel-only
notifier interface, the client queue (CONFIG_KPB_CLI_Q), which can
also be used from user space.

Replace the k_queue with a statically defined k_msgq that carries
struct kpb_client by value, and replace kpb_notifier_init() and
kpb_notifier_schedule() with a single kpb_notifier_schedule(id,
drain_req) syscall taking only scalar arguments. No pointers are passed
from user space to the kernel.

As before, only a single KPB instance is supported.

With the client queue, draining setup runs in the client queue thread
instead of the LL thread, so lock the scheduler around
kpb_init_draining() to keep kpb_copy() from preempting it. The thread
is pinned to the KPB core, so this is sufficient.

Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Queued requests can dereference missing sinks and fault the kernel thread across lifecycle changes, while zero-length requests can leave KPB stuck draining with the detector paused.

2 open issues
What changed in this PR

This PR makes the KPB service callable from user space through the client queue while preserving the kernel-only notifier interface and single-instance restriction.

Changes:

  • Replaces the pointer-based queue interface with a static message queue and scalar-only scheduling syscall.
  • Adds client-queue support and error propagation to the module service bridge.
  • Locks scheduling during draining setup to prevent interference from the audio copy thread.
File Description
zephyr/​syscall/​kpb.c Adds the scheduling syscall verification wrapper.
zephyr/​CMakeLists.txt Builds the wrapper for user-space client-queue configurations.
src/​include/​sof/​audio/​kpb.h Declares the scalar syscall and removes client pointers.
src/​audio/​module_adapter/​library/​kpb_service_bridge.c Routes draining requests through the queue and maps errors.
src/​audio/​module_adapter/​Kconfig Avoids selecting the notifier when the client queue is enabled.
src/​audio/​kpb.c Implements value-based queueing, instance lifecycle handling, and scheduler locking.

Review effort: Balanced

Comment thread src/audio/kpb.c Resolved
Comment thread src/audio/kpb.c Resolved
@intel-sofci

intel-sofci commented Nov 9, 2026 •

Copy link
Copy Markdown

PR 11425: test results

Run date: 2026-11-10 14:05 UTC

Tested commit: ef71b65abd91f1d5e72e9b68ca7814d0f03b5407

mtl pass rate lnl pass rate ptl pass rate wcl pass rate nvl pass rate

kpb_init_draining() reads the host sink state before checking the KPB
state, but host_sink and sel_sink are NULL before bind and after
reset/unbind. As draining can potentially be requested at any time while
the KPB instance exists, such a request would dereference a NULL sink.

Treat the sink as not ready if either sink is missing.

Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
A draining request of 0 ms, i.e. no history, only the real time stream,
is accepted by kpb_init_draining(), which pauses the selector and moves
KPB to KPB_STATE_DRAINING. However, kpb_draining_task() only picks up
data buffered while draining and switches to KPB_STATE_HOST_COPY inside
the drain_req > 0 block, so with a zero request it completes without
ever leaving KPB_STATE_DRAINING, leaving KPB stuck with the detector
paused and rejecting further requests.

Move the drain completion handling out of that block so it also runs
for a zero-length request.

Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
Comment thread src/audio/kpb.c
kpb_init_draining(cli->dev, cli);
k_msgq_get(&kpb_cli_msgq, &cli, K_FOREVER);
/* keep the LL thread (kpb_copy()) from preempting draining setup */
k_sched_lock();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We haven't used this k_sched_lock() interface much. Seems to be ok here...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants