From 9ccbea0f114053e59d33cbc31a284daad94bc62b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0erif=20Rami?= Date: Fri, 8 Aug 2025 18:40:02 +0200 Subject: [PATCH] more stability fixes --- us144mkii.c | 3 +++ us144mkii.h | 10 ++++++++++ us144mkii_playback.c | 22 ++++++++++++++++++---- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/us144mkii.c b/us144mkii.c index 2cf06be..6571288 100644 --- a/us144mkii.c +++ b/us144mkii.c @@ -332,6 +332,7 @@ static int tascam_suspend(struct usb_interface *intf, pm_message_t message) { cancel_work_sync(&tascam->capture_work); cancel_work_sync(&tascam->midi_in_work); cancel_work_sync(&tascam->midi_out_work); + cancel_work_sync(&tascam->stop_pcm_work); usb_kill_anchored_urbs(&tascam->playback_anchor); usb_kill_anchored_urbs(&tascam->capture_anchor); usb_kill_anchored_urbs(&tascam->feedback_anchor); @@ -494,6 +495,7 @@ static int tascam_probe(struct usb_interface *intf, timer_setup(&tascam->error_timer, tascam_error_timer, 0); INIT_WORK(&tascam->stop_work, tascam_stop_work_handler); + INIT_WORK(&tascam->stop_pcm_work, tascam_stop_pcm_work_handler); if (kfifo_alloc(&tascam->midi_in_fifo, MIDI_IN_FIFO_SIZE, GFP_KERNEL)) { snd_card_free(card); @@ -576,6 +578,7 @@ static void tascam_disconnect(struct usb_interface *intf) { cancel_work_sync(&tascam->capture_work); cancel_work_sync(&tascam->midi_in_work); cancel_work_sync(&tascam->midi_out_work); + cancel_work_sync(&tascam->stop_pcm_work); usb_kill_anchored_urbs(&tascam->playback_anchor); usb_kill_anchored_urbs(&tascam->capture_anchor); diff --git a/us144mkii.h b/us144mkii.h index 980ed85..04b8293 100644 --- a/us144mkii.h +++ b/us144mkii.h @@ -258,6 +258,7 @@ struct tascam_card { // Work structs struct work_struct capture_work; struct work_struct stop_work; + struct work_struct stop_pcm_work; struct work_struct midi_in_work; struct work_struct midi_out_work; @@ -310,6 +311,15 @@ int tascam_alloc_urbs(struct tascam_card *tascam); */ void tascam_stop_work_handler(struct work_struct *work); +/** + * tascam_stop_pcm_work_handler() - Work handler to stop PCM streams. + * @work: Pointer to the work_struct. + * + * This function is scheduled to stop PCM streams (playback and capture) + * from a workqueue context, avoiding blocking operations in interrupt context. + */ +void tascam_stop_pcm_work_handler(struct work_struct *work); + /* us144mkii_pcm.h */ #include "us144mkii_pcm.h" diff --git a/us144mkii_playback.c b/us144mkii_playback.c index fcc03ef..3028312 100644 --- a/us144mkii_playback.c +++ b/us144mkii_playback.c @@ -343,10 +343,7 @@ void feedback_urb_complete(struct urb *urb) { FEEDBACK_SYNC_LOSS_THRESHOLD) { dev_err(tascam->card->dev, "Fatal: Feedback sync lost. Stopping stream.\n"); - if (playback_ss) - snd_pcm_stop(playback_ss, SNDRV_PCM_STATE_XRUN); - if (capture_ss) - snd_pcm_stop(capture_ss, SNDRV_PCM_STATE_XRUN); + schedule_work(&tascam->stop_pcm_work); tascam->feedback_synced = false; goto continue_unlock; } @@ -427,3 +424,20 @@ continue_unlock: out: usb_put_urb(urb); } + +/** + * tascam_stop_pcm_work_handler() - Work handler to stop PCM streams. + * @work: Pointer to the work_struct. + * + * This function is scheduled to stop PCM streams (playback and capture) + * from a workqueue context, avoiding blocking operations in interrupt context. + */ +void tascam_stop_pcm_work_handler(struct work_struct *work) { + struct tascam_card *tascam = + container_of(work, struct tascam_card, stop_pcm_work); + + if (tascam->playback_substream) + snd_pcm_stop(tascam->playback_substream, SNDRV_PCM_STATE_XRUN); + if (tascam->capture_substream) + snd_pcm_stop(tascam->capture_substream, SNDRV_PCM_STATE_XRUN); +}