From f600f6c4824d7e40be370f7e26ab0fbc3f6f911c Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Thu, 16 Apr 2009 19:35:01 +0200 Subject: [PATCH 1/2] ALSA: us122l: Fix signedness in comparisions Within 2.6.30's mergewindow, struct urb's transfer_buffer_length has become unsigned. This changed an "int > int" comparision to an "unsigned > int" one in snd_usb_122l. Fix this by using a local int variable instead of urb->transfer_buffer_length in comparisions. Shorten playback_prep_freqn() a bit and tweak error-paths in usb_stream_prepare_playback(). Signed-off-by: Karsten Wiese Signed-off-by: Takashi Iwai --- sound/usb/usx2y/usb_stream.c | 65 ++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 24393dafcb6e..12ae0340adc0 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -33,32 +33,26 @@ static unsigned usb_stream_next_packet_size(struct usb_stream_kernel *sk) static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb) { struct usb_stream *s = sk->s; - unsigned l = 0; - int pack; + int pack, lb = 0; - urb->iso_frame_desc[0].offset = 0; - urb->iso_frame_desc[0].length = usb_stream_next_packet_size(sk); - sk->out_phase = sk->out_phase_peeked; - urb->transfer_buffer_length = urb->iso_frame_desc[0].length; - - for (pack = 1; pack < sk->n_o_ps; pack++) { - l = usb_stream_next_packet_size(sk); - if (s->idle_outsize + urb->transfer_buffer_length + l > - s->period_size) + for (pack = 0; pack < sk->n_o_ps; pack++) { + int l = usb_stream_next_packet_size(sk); + if (s->idle_outsize + lb + l > s->period_size) goto check; sk->out_phase = sk->out_phase_peeked; - urb->iso_frame_desc[pack].offset = urb->transfer_buffer_length; + urb->iso_frame_desc[pack].offset = lb; urb->iso_frame_desc[pack].length = l; - urb->transfer_buffer_length += l; + lb += l; } - snd_printdd(KERN_DEBUG "%i\n", urb->transfer_buffer_length); + snd_printdd(KERN_DEBUG "%i\n", lb); check: urb->number_of_packets = pack; - s->idle_outsize += urb->transfer_buffer_length - s->period_size; + urb->transfer_buffer_length = lb; + s->idle_outsize += lb - s->period_size; snd_printdd(KERN_DEBUG "idle=%i ul=%i ps=%i\n", s->idle_outsize, - urb->transfer_buffer_length, s->period_size); + lb, s->period_size); } static void init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, @@ -282,21 +276,20 @@ static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, struct usb_stream *s = sk->s; struct urb *io; struct usb_iso_packet_descriptor *id, *od; - int p, l = 0; + int p = 0, lb = 0, l = 0; io = sk->idle_outurb; od = io->iso_frame_desc; - io->transfer_buffer_length = 0; - for (p = 0; s->sync_packet < 0; ++p, ++s->sync_packet) { + for (; s->sync_packet < 0; ++p, ++s->sync_packet) { struct urb *ii = sk->completed_inurb; id = ii->iso_frame_desc + ii->number_of_packets + s->sync_packet; l = id->actual_length; od[p].length = l; - od[p].offset = io->transfer_buffer_length; - io->transfer_buffer_length += l; + od[p].offset = lb; + lb += l; } for (; @@ -304,38 +297,38 @@ static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, ++p, ++s->sync_packet) { l = inurb->iso_frame_desc[s->sync_packet].actual_length; - if (s->idle_outsize + io->transfer_buffer_length + l > - s->period_size) + if (s->idle_outsize + lb + l > s->period_size) goto check_ok; od[p].length = l; - od[p].offset = io->transfer_buffer_length; - io->transfer_buffer_length += l; + od[p].offset = lb; + lb += l; } check_ok: s->sync_packet -= inurb->number_of_packets; - if (s->sync_packet < -2 || s->sync_packet > 0) { + if (unlikely(s->sync_packet < -2 || s->sync_packet > 0)) { snd_printk(KERN_WARNING "invalid sync_packet = %i;" " p=%i nop=%i %i %x %x %x > %x\n", s->sync_packet, p, inurb->number_of_packets, - s->idle_outsize + io->transfer_buffer_length + l, - s->idle_outsize, io->transfer_buffer_length, l, + s->idle_outsize + lb + l, + s->idle_outsize, lb, l, s->period_size); return -1; } - if (io->transfer_buffer_length % s->cfg.frame_size) { + if (unlikely(lb % s->cfg.frame_size)) { snd_printk(KERN_WARNING"invalid outsize = %i\n", - io->transfer_buffer_length); + lb); return -1; } - s->idle_outsize += io->transfer_buffer_length - s->period_size; + s->idle_outsize += lb - s->period_size; io->number_of_packets = p; - if (s->idle_outsize > 0) { - snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize); - return -1; - } - return 0; + io->transfer_buffer_length = lb; + if (s->idle_outsize <= 0) + return 0; + + snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize); + return -1; } static void prepare_inurb(int number_of_packets, struct urb *iu) From 5d4af1be06affa2b42cdf59cd376752be1f934b3 Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Mon, 20 Apr 2009 13:01:21 +0200 Subject: [PATCH 2/2] ALSA: us122l: add snd_us122l_free() Use it to clean up snd_us122l_card_used[]. Without patch unplugging of an US122L soundcard didn't reset the corresponding element of snd_us122l_card_used[] to 0. The (SNDRV_CARDS + 1)th plugging in did not result in creating the soundcard device anymore. Index values supplied with the modprobe command line were not used correctly anymore after the first unplugging of an US122L. Signed-off-by: Karsten Wiese Cc: stable@kernel.org Signed-off-by: Takashi Iwai --- sound/usb/usx2y/us122l.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 98276aafefe6..463f3ffe3fb9 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -478,6 +478,14 @@ static bool us122l_create_card(struct snd_card *card) return true; } +static void snd_us122l_free(struct snd_card *card) +{ + struct us122l *us122l = US122L(card); + int index = us122l->chip.index; + if (index >= 0 && index < SNDRV_CARDS) + snd_us122l_card_used[index] = 0; +} + static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) { int dev; @@ -494,7 +502,7 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) if (err < 0) return err; snd_us122l_card_used[US122L(card)->chip.index = dev] = 1; - + card->private_free = snd_us122l_free; US122L(card)->chip.dev = device; US122L(card)->chip.card = card; mutex_init(&US122L(card)->mutex); @@ -588,7 +596,7 @@ static void snd_us122l_disconnect(struct usb_interface *intf) } usb_put_intf(intf); - usb_put_dev(US122L(card)->chip.dev); + usb_put_dev(us122l->chip.dev); while (atomic_read(&us122l->mmap_count)) msleep(500);