more stability fixes

This commit is contained in:
Šerif Rami 2025-08-08 18:40:02 +02:00
parent 196cd55787
commit 9ccbea0f11
3 changed files with 31 additions and 4 deletions

View File

@ -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->capture_work);
cancel_work_sync(&tascam->midi_in_work); cancel_work_sync(&tascam->midi_in_work);
cancel_work_sync(&tascam->midi_out_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->playback_anchor);
usb_kill_anchored_urbs(&tascam->capture_anchor); usb_kill_anchored_urbs(&tascam->capture_anchor);
usb_kill_anchored_urbs(&tascam->feedback_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); timer_setup(&tascam->error_timer, tascam_error_timer, 0);
INIT_WORK(&tascam->stop_work, tascam_stop_work_handler); 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)) { if (kfifo_alloc(&tascam->midi_in_fifo, MIDI_IN_FIFO_SIZE, GFP_KERNEL)) {
snd_card_free(card); 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->capture_work);
cancel_work_sync(&tascam->midi_in_work); cancel_work_sync(&tascam->midi_in_work);
cancel_work_sync(&tascam->midi_out_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->playback_anchor);
usb_kill_anchored_urbs(&tascam->capture_anchor); usb_kill_anchored_urbs(&tascam->capture_anchor);

View File

@ -258,6 +258,7 @@ struct tascam_card {
// Work structs // Work structs
struct work_struct capture_work; struct work_struct capture_work;
struct work_struct stop_work; struct work_struct stop_work;
struct work_struct stop_pcm_work;
struct work_struct midi_in_work; struct work_struct midi_in_work;
struct work_struct midi_out_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); 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 */ /* us144mkii_pcm.h */
#include "us144mkii_pcm.h" #include "us144mkii_pcm.h"

View File

@ -343,10 +343,7 @@ void feedback_urb_complete(struct urb *urb) {
FEEDBACK_SYNC_LOSS_THRESHOLD) { FEEDBACK_SYNC_LOSS_THRESHOLD) {
dev_err(tascam->card->dev, dev_err(tascam->card->dev,
"Fatal: Feedback sync lost. Stopping stream.\n"); "Fatal: Feedback sync lost. Stopping stream.\n");
if (playback_ss) schedule_work(&tascam->stop_pcm_work);
snd_pcm_stop(playback_ss, SNDRV_PCM_STATE_XRUN);
if (capture_ss)
snd_pcm_stop(capture_ss, SNDRV_PCM_STATE_XRUN);
tascam->feedback_synced = false; tascam->feedback_synced = false;
goto continue_unlock; goto continue_unlock;
} }
@ -427,3 +424,20 @@ continue_unlock:
out: out:
usb_put_urb(urb); 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);
}