diff --git a/us144mkii.c b/us144mkii.c index 1d5fca7..ef0159c 100644 --- a/us144mkii.c +++ b/us144mkii.c @@ -157,9 +157,6 @@ void tascam_stop_work_handler(struct work_struct *work) usb_kill_anchored_urbs(&tascam->playback_anchor); usb_kill_anchored_urbs(&tascam->feedback_anchor); - usb_kill_anchored_urbs(&tascam->capture_anchor); - usb_kill_anchored_urbs(&tascam->midi_anchor); - atomic_set(&tascam->active_urbs, 0); } static void tascam_card_private_free(struct snd_card *card) diff --git a/us144mkii_capture.c b/us144mkii_capture.c index f56eb14..aab7054 100644 --- a/us144mkii_capture.c +++ b/us144mkii_capture.c @@ -195,11 +195,6 @@ void capture_urb_complete(struct urb *urb) return; } - if (!atomic_read(&tascam->capture_active)) { - atomic_dec(&tascam->active_urbs); - return; - } - substream = tascam->capture_substream; if (!substream || !substream->runtime) { atomic_dec(&tascam->active_urbs); @@ -220,8 +215,14 @@ void capture_urb_complete(struct urb *urb) if (frames_received > 0) { spin_lock_irqsave(&tascam->lock, flags); + + if (!atomic_read(&tascam->capture_active)) { + spin_unlock_irqrestore(&tascam->lock, flags); + atomic_dec(&tascam->active_urbs); + return; + } + write_pos = tascam->driver_capture_pos; - spin_unlock_irqrestore(&tascam->lock, flags); u32 *dma_ptr = (u32 *)(runtime->dma_area + frames_to_bytes(runtime, write_pos)); @@ -235,7 +236,6 @@ void capture_urb_complete(struct urb *urb) tascam_decode_capture_chunk(urb->transfer_buffer + (part1 * 64), (u32 *)runtime->dma_area, part2); } - spin_lock_irqsave(&tascam->lock, flags); tascam->driver_capture_pos += frames_received; if (tascam->driver_capture_pos >= buffer_size) tascam->driver_capture_pos -= buffer_size; diff --git a/us144mkii_midi.c b/us144mkii_midi.c index 005b301..d58f936 100644 --- a/us144mkii_midi.c +++ b/us144mkii_midi.c @@ -6,6 +6,7 @@ static void tascam_midi_out_complete(struct urb *urb) { struct tascam_card *tascam = urb->context; + struct snd_rawmidi_substream *substream; unsigned long flags; int count; bool submit = false; @@ -13,19 +14,20 @@ static void tascam_midi_out_complete(struct urb *urb) spin_lock_irqsave(&tascam->midi_lock, flags); - if (urb->status || !tascam->midi_output) { + substream = tascam->midi_output; + active = tascam->midi_out_active; + + if (urb->status || !substream) { tascam->midi_out_active = false; spin_unlock_irqrestore(&tascam->midi_lock, flags); return; } - - active = tascam->midi_out_active; spin_unlock_irqrestore(&tascam->midi_lock, flags); if (!active) return; - count = snd_rawmidi_transmit(tascam->midi_output, tascam->midi_out_buf, MIDI_PAYLOAD_SIZE); + count = snd_rawmidi_transmit(substream, tascam->midi_out_buf, MIDI_PAYLOAD_SIZE); if (count > 0) { if (count < MIDI_PAYLOAD_SIZE) memset(tascam->midi_out_buf + count, 0xFD, MIDI_PAYLOAD_SIZE - count); @@ -98,18 +100,24 @@ static void tascam_midi_output_trigger(struct snd_rawmidi_substream *substream, static void tascam_midi_in_complete(struct urb *urb) { struct tascam_card *tascam = urb->context; + struct snd_rawmidi_substream *substream; + unsigned long flags; int i; if (urb->status) return; - if (urb->actual_length == MIDI_PACKET_SIZE && tascam->midi_input) { + spin_lock_irqsave(&tascam->midi_lock, flags); + substream = tascam->midi_input; + spin_unlock_irqrestore(&tascam->midi_lock, flags); + + if (urb->actual_length == MIDI_PACKET_SIZE && substream) { u8 *data = urb->transfer_buffer; for (i = 0; i < MIDI_PAYLOAD_SIZE; i++) { if (data[i] == 0xFD) break; - snd_rawmidi_receive(tascam->midi_input, &data[i], 1); + snd_rawmidi_receive(substream, &data[i], 1); } } @@ -121,11 +129,14 @@ static void tascam_midi_in_complete(struct urb *urb) static void tascam_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { struct tascam_card *tascam = substream->rmidi->private_data; + unsigned long flags; + spin_lock_irqsave(&tascam->midi_lock, flags); if (up) tascam->midi_input = substream; else tascam->midi_input = NULL; + spin_unlock_irqrestore(&tascam->midi_lock, flags); } static int tascam_midi_open(struct snd_rawmidi_substream *substream) @@ -238,15 +249,15 @@ int tascam_create_midi(struct tascam_card *tascam) return 0; -err_in_buf: + err_in_buf: usb_free_coherent(tascam->dev, MIDI_PACKET_SIZE, tascam->midi_out_buf, tascam->midi_out_urb->transfer_dma); -err_out_buf: + err_out_buf: usb_free_urb(tascam->midi_in_urb); tascam->midi_in_urb = NULL; -err_in_urb: + err_in_urb: usb_free_urb(tascam->midi_out_urb); tascam->midi_out_urb = NULL; -err_out_urb: + err_out_urb: return err; } diff --git a/us144mkii_pcm.c b/us144mkii_pcm.c index acc432f..86d0ad9 100644 --- a/us144mkii_pcm.c +++ b/us144mkii_pcm.c @@ -122,6 +122,10 @@ int tascam_pcm_hw_params(struct snd_pcm_substream *substream, int err; if (tascam->current_rate != rate) { + if (atomic_read(&tascam->playback_active) || + atomic_read(&tascam->capture_active)) { + return -EBUSY; + } usb_kill_anchored_urbs(&tascam->playback_anchor); usb_kill_anchored_urbs(&tascam->feedback_anchor); diff --git a/us144mkii_playback.c b/us144mkii_playback.c index f2ed42c..860912c 100644 --- a/us144mkii_playback.c +++ b/us144mkii_playback.c @@ -214,10 +214,6 @@ void playback_urb_complete(struct urb *urb) atomic_dec(&tascam->active_urbs); return; } - if (!atomic_read(&tascam->playback_active)) { - atomic_dec(&tascam->active_urbs); - return; - } substream = tascam->playback_substream; if (!substream || !substream->runtime) { @@ -234,6 +230,13 @@ void playback_urb_complete(struct urb *urb) period_size = runtime->period_size; spin_lock_irqsave(&tascam->lock, flags); + + if (!atomic_read(&tascam->playback_active)) { + spin_unlock_irqrestore(&tascam->lock, flags); + atomic_dec(&tascam->active_urbs); + return; + } + for (i = 0; i < urb->number_of_packets; i++) { unsigned int frames_for_packet; @@ -249,7 +252,6 @@ void playback_urb_complete(struct urb *urb) offset_frames = tascam->driver_playback_pos; frames_to_copy = bytes_to_frames(runtime, total_bytes_for_urb); tascam->driver_playback_pos = (offset_frames + frames_to_copy) % buffer_size; - spin_unlock_irqrestore(&tascam->lock, flags); if (total_bytes_for_urb > 0) { u8 *dst_buf = urb->transfer_buffer; @@ -265,7 +267,6 @@ void playback_urb_complete(struct urb *urb) } } - spin_lock_irqsave(&tascam->lock, flags); tascam->playback_frames_consumed += frames_to_copy; if (period_size > 0) {