Commit f3f80a92 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: caiaq - Fix Oops with MIDI

The snd-usb-caiaq driver causes Oops occasionally when accessing MIDI
devices.  This patch fixes the Oops and invalid URB submission errors
as well.

Cc: stable@kernel.org
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 9e42d0cf
...@@ -75,6 +75,7 @@ struct snd_usb_caiaqdev { ...@@ -75,6 +75,7 @@ struct snd_usb_caiaqdev {
wait_queue_head_t ep1_wait_queue; wait_queue_head_t ep1_wait_queue;
wait_queue_head_t prepare_wait_queue; wait_queue_head_t prepare_wait_queue;
int spec_received, audio_parm_answer; int spec_received, audio_parm_answer;
int midi_out_active;
char vendor_name[CAIAQ_USB_STR_LEN]; char vendor_name[CAIAQ_USB_STR_LEN];
char product_name[CAIAQ_USB_STR_LEN]; char product_name[CAIAQ_USB_STR_LEN];
......
...@@ -59,6 +59,11 @@ static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substrea ...@@ -59,6 +59,11 @@ static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substrea
static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream) static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream)
{ {
struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
if (dev->midi_out_active) {
usb_kill_urb(&dev->midi_out_urb);
dev->midi_out_active = 0;
}
return 0; return 0;
} }
...@@ -69,7 +74,8 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, ...@@ -69,7 +74,8 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev,
dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE;
dev->midi_out_buf[1] = 0; /* port */ dev->midi_out_buf[1] = 0; /* port */
len = snd_rawmidi_transmit_peek(substream, dev->midi_out_buf+3, EP1_BUFSIZE-3); len = snd_rawmidi_transmit(substream, dev->midi_out_buf + 3,
EP1_BUFSIZE - 3);
if (len <= 0) if (len <= 0)
return; return;
...@@ -79,24 +85,24 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, ...@@ -79,24 +85,24 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev,
ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC);
if (ret < 0) if (ret < 0)
log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed, %d\n", log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed,"
substream, ret); "ret=%d, len=%d\n",
substream, ret, len);
else
dev->midi_out_active = 1;
} }
static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{ {
struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
if (dev->midi_out_substream != NULL) if (up) {
return; dev->midi_out_substream = substream;
if (!dev->midi_out_active)
if (!up) { snd_usb_caiaq_midi_send(dev, substream);
} else {
dev->midi_out_substream = NULL; dev->midi_out_substream = NULL;
return;
} }
dev->midi_out_substream = substream;
snd_usb_caiaq_midi_send(dev, substream);
} }
...@@ -161,16 +167,14 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device) ...@@ -161,16 +167,14 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
void snd_usb_caiaq_midi_output_done(struct urb* urb) void snd_usb_caiaq_midi_output_done(struct urb* urb)
{ {
struct snd_usb_caiaqdev *dev = urb->context; struct snd_usb_caiaqdev *dev = urb->context;
char *buf = urb->transfer_buffer;
dev->midi_out_active = 0;
if (urb->status != 0) if (urb->status != 0)
return; return;
if (!dev->midi_out_substream) if (!dev->midi_out_substream)
return; return;
snd_rawmidi_transmit_ack(dev->midi_out_substream, buf[2]);
dev->midi_out_substream = NULL;
snd_usb_caiaq_midi_send(dev, dev->midi_out_substream); snd_usb_caiaq_midi_send(dev, dev->midi_out_substream);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment