From 05ef392f96688bb1e9628c821da3ea75dca38215 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 25 Aug 2009 08:15:41 +0200 Subject: [PATCH] sound: pcm_lib: fix unsorted list constraint handling commit b1ddaf681e362ed453182ddee1699d7487069a16 upstream. snd_interval_list() expected a sorted list but did not document this, so there are drivers that give it an unsorted list. To fix this, change the algorithm to work with any list. This fixes the "Slave PCM not usable" error with USB devices that have multiple alternate settings with sample rates in decreasing order, such as the Philips Askey VC010 WebCam. http://bugzilla.kernel.org/show_bug.cgi?id=14028 Reported-and-tested-by: Andrzej Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/core/pcm_lib.c | 39 ++++++++------------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index d659995ac3ac7..2a2c2cab352c8 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -876,47 +876,24 @@ static int snd_interval_ratden(struct snd_interval *i, int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask) { unsigned int k; - int changed = 0; + struct snd_interval list_range; if (!count) { i->empty = 1; return -EINVAL; } + snd_interval_any(&list_range); + list_range.min = UINT_MAX; + list_range.max = 0; for (k = 0; k < count; k++) { if (mask && !(mask & (1 << k))) continue; - if (i->min == list[k] && !i->openmin) - goto _l1; - if (i->min < list[k]) { - i->min = list[k]; - i->openmin = 0; - changed = 1; - goto _l1; - } - } - i->empty = 1; - return -EINVAL; - _l1: - for (k = count; k-- > 0;) { - if (mask && !(mask & (1 << k))) + if (!snd_interval_test(i, list[k])) continue; - if (i->max == list[k] && !i->openmax) - goto _l2; - if (i->max > list[k]) { - i->max = list[k]; - i->openmax = 0; - changed = 1; - goto _l2; - } + list_range.min = min(list_range.min, list[k]); + list_range.max = max(list_range.max, list[k]); } - i->empty = 1; - return -EINVAL; - _l2: - if (snd_interval_checkempty(i)) { - i->empty = 1; - return -EINVAL; - } - return changed; + return snd_interval_refine(i, &list_range); } EXPORT_SYMBOL(snd_interval_list); -- 2.47.2