Skip to content

apple-bce: fix scheduling while atomic and playback timestamp#50

Open
Vakarux12 wants to merge 2 commits into
t2linux:mainfrom
Vakarux12:fix-aaudio-scheduling-while-atomic
Open

apple-bce: fix scheduling while atomic and playback timestamp#50
Vakarux12 wants to merge 2 commits into
t2linux:mainfrom
Vakarux12:fix-aaudio-scheduling-while-atomic

Conversation

@Vakarux12

Copy link
Copy Markdown

Syncs the bundled apple-bce driver with fixes from t2linux/apple-bce-drv#31.

Fix 1: skip period_elapsed for streams that are not started

Symptom: Connecting speakers or headphones to the 3.5mm jack causes BUG: scheduling while atomic in irq/bce_dma, followed by a flood of aaudio_pcm_pointer while not started messages. System becomes unresponsive for audio.

Cause: The T2 chip sends timestamp events for all registered audio devices continuously, even when no ALSA stream is open. aaudio_handle_stream_timestamp() was unconditionally calling snd_pcm_period_elapsed(), which on a stopped stream chains into snd_pcm_do_stopaaudio_pcm_trigger(STOP)wait_for_completion_timeout(). The BCE DMA IRQ handler runs with BHs disabled, so any attempt to sleep triggers the bug.

Fix: Return early when stream->started == 0, matching the guard already in aaudio_pcm_pointer().

Fix 2: use os_timestamp for PLAYBACK

Cause: aaudio_handle_timestamp() was passing dev_timestamp (T2 clock domain) to the PLAYBACK substream while CAPTURE correctly used os_timestamp. After suspend/resume or module re-probe the T2 clock drifts, causing wild PCM positions and XRUNs.

Fix: Use os_timestamp for both PLAYBACK and CAPTURE.

Tested

MacBookPro16,1, kernel 7.0.12-arch1-Watanare-T2-1-t2, PREEMPT(full). Before: connecting speakers crashed audio. After: clean kernel log, audio works on both speakers and headphones.

Two fixes to the bundled apple-bce driver, syncing with upstream
t2linux/apple-bce-drv:

1. audio/pcm: skip period_elapsed for streams that are not started

   The T2 chip sends timestamp events for all devices continuously.
   Calling snd_pcm_period_elapsed() on a stopped stream causes the ALSA
   state machine to call aaudio_pcm_trigger(STOP), which blocks on
   wait_for_completion_timeout(). On PREEMPT(full) kernels the BCE DMA
   IRQ handler runs with BHs disabled, so this triggers:
   BUG: scheduling while atomic

   Fix: return early when stream->started == 0.

2. audio/pcm: use os_timestamp for PLAYBACK in aaudio_handle_timestamp

   PLAYBACK was using dev_timestamp (T2 clock domain) while CAPTURE
   correctly used os_timestamp. After module re-probe the T2 clock can
   drift, causing wild PCM positions and XRUNs. Use os_timestamp for
   both streams.
aaudio_cmd_stop_io blocks waiting for a T2 reply. When called from
PCM trigger(STOP) it can block PipeWire's main thread while the RT
data thread holds a PI mutex the main thread needs, causing a deadlock.
It can also be called from atomic context (BCE DMA BH handler) causing
scheduling-while-atomic.

Always defer via schedule_work. In trigger(START) use cancel_work_sync
to cancel any pending stop before starting without blocking callers.
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.

1 participant