Re: [PATCH 1/2] firmware: samsung: acpm: add fire-and-forget xfer support
From: Tudor Ambarus
Date: Thu Sep 10 2026 - 09:25:27 EST
Hi, Alexey,
Sorry for the delay.
And thanks for the series. Improving frequency transition latency by
giving schedutil an atomic ->fast_switch() path is definitely a
worthwhile goal.
On 6/12/26 7:34 AM, Alexey Klimov wrote:
> The current ACPM IPC protocol relies on synchronous polling
> (acpm_dequeue_by_polling) to process mailbox responses.
> For CPU DVFS, cpufreqs schedutil governor requires ->fast_switch() to
> execute in an atomic context. Waiting for firmware acknowledgments
> in a loop in such case also using udelay(20) under spinlock doesn't
> make a lot of sense. Experiemnts on Exynos850 showed that even with
> removed udelay() or with it significantly decreased, the firmware
> processing takes 15us...250us.
>
> Introduce acpm_do_xfer_fast(), which implements a fire-and-forget
> asynchronous path:
> - utilizes spin_trylock() to exit without sleeping if the channel
> is busy;
> - adds/sends the message and kicks the mailbox doorbell;
> - exits immediately, allowing fast_switch to complete quickly.
>
> To prevent the unread asynchronous responses from permanently exhausting
> the 63-slot sequence ring buffer, implement an acpm_drain_stale_rx().
> This drains the RX queue during the fast path:
> - copies payloads and sets completion flags for sleeping
> synchronous users;
> - explicitly acks 'is_async' messages.
Answering your core question directly: the fire-and-forget approach
over the existing ACPM command queue (acpm_do_xfer_fast) won't fly.
The ACPM IPC protocol is fundamentally a half-duplex, synchronous
request-response mechanism over SRAM ring buffers.
Even if the host sets response = false, the ACPM firmware does not have
a concept of fire-and-forget on standard command queues. It executes the
transition and still pushes a completion entry into the SRAM RX queue,
advancing rx.front.
Draining stale RX entries opportunistically on the next xfer via
acpm_drain_stale_rx() is fragile:
1. If frequency transitions stop (e.g. CPU hits target frequency and
stays there), rx.rear is never advanced, leaving stale responses in
SRAM indefinitely.
2. Queue lengths (qlen) in ACPM SRAM are small. If schedutil issues a
burst of frequency changes faster than the firmware completes them,
the RX queue fills up. When rx.front == rx.rear the firmware panics.
3. If spin_trylock(&achan->rx_lock) fails, acpm_drain_stale_rx()
silently aborts, and sequence numbers in achan->bitmap_seqnum leak
until the pool is exhausted (-EBUSY).
For addressing fast switch, I see downstream that the firmware defines
a dedicated channel of type TYPE_BUFFER (async_dvfs). Frequency changes
simply write the frequency into the SRAM cell and ring a direct MMIO
doorbell:
(https://android.googlesource.com/kernel/google-modules/soc/gs/+/refs/heads/android-gs-raviole-6.1-android16/drivers/soc/google/cal-if/acpm_dvfs.c#97)
async_dvfs_set_requested_freq(id, rate); /* 32-bit SRAM write */
acpm_ipc_ring_doorbell(async_ch_num); /* MMIO doorbell */
There are no ring buffers, no sequence numbers, no polling, and no
RX responses to drain. This is essentially an SCMI FastChannel-style
interface.
Is e850 supporting this?
Cheers,
ta