This is a note to let you know that I've just added the patch titled ALSA: usb-audio: Restrict rates for the shared clocks to the 5.15-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: alsa-usb-audio-restrict-rates-for-the-shared-clocks.patch and it can be found in the queue-5.15 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From 4e7cf1fbb34ecb472c073980458cbe413afd4d64 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@xxxxxxx> Date: Wed, 29 Sep 2021 10:08:36 +0200 Subject: ALSA: usb-audio: Restrict rates for the shared clocks From: Takashi Iwai <tiwai@xxxxxxx> commit 4e7cf1fbb34ecb472c073980458cbe413afd4d64 upstream. When a single clock source is shared among several endpoints, we have to keep the same rate on all active endpoints as long as the clock is being used. For dealing with such a case, this patch adds one more check in the hw params constraint for the rate to take the shared clocks into account. The current rate is evaluated from the endpoint list that applies the same clock source. BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1190418 Link: https://lore.kernel.org/r/20210929080844.11583-2-tiwai@xxxxxxx Signed-off-by: Takashi Iwai <tiwai@xxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- sound/usb/card.h | 1 + sound/usb/endpoint.c | 21 +++++++++++++++++++++ sound/usb/endpoint.h | 1 + sound/usb/pcm.c | 9 +++++++++ 4 files changed, 32 insertions(+) --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -137,6 +137,7 @@ struct snd_usb_endpoint { unsigned int cur_period_frames; unsigned int cur_period_bytes; unsigned int cur_buffer_periods; + unsigned char cur_clock; spinlock_t lock; struct list_head list; --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -726,6 +726,7 @@ snd_usb_endpoint_open(struct snd_usb_aud ep->cur_period_frames = params_period_size(params); ep->cur_period_bytes = ep->cur_period_frames * ep->cur_frame_bytes; ep->cur_buffer_periods = params_periods(params); + ep->cur_clock = fp->clock; if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC) endpoint_set_syncinterval(chip, ep); @@ -837,6 +838,7 @@ void snd_usb_endpoint_close(struct snd_u ep->altsetting = 0; ep->cur_audiofmt = NULL; ep->cur_rate = 0; + ep->cur_clock = 0; ep->iface_ref = NULL; usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num); } @@ -1344,6 +1346,25 @@ unlock: return err; } +/* get the current rate set to the given clock by any endpoint */ +int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock) +{ + struct snd_usb_endpoint *ep; + int rate = 0; + + if (!clock) + return 0; + mutex_lock(&chip->mutex); + list_for_each_entry(ep, &chip->ep_list, list) { + if (ep->cur_clock == clock && ep->cur_rate) { + rate = ep->cur_rate; + break; + } + } + mutex_unlock(&chip->mutex); + return rate; +} + /** * snd_usb_endpoint_start: start an snd_usb_endpoint * --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -19,6 +19,7 @@ void snd_usb_endpoint_close(struct snd_u struct snd_usb_endpoint *ep); int snd_usb_endpoint_configure(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep); +int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock); bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep, --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -734,6 +734,7 @@ static int hw_rule_rate(struct snd_pcm_h struct snd_pcm_hw_rule *rule) { struct snd_usb_substream *subs = rule->private; + struct snd_usb_audio *chip = subs->stream->chip; const struct audioformat *fp; struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); unsigned int rmin, rmax, r; @@ -745,6 +746,14 @@ static int hw_rule_rate(struct snd_pcm_h list_for_each_entry(fp, &subs->fmt_list, list) { if (!hw_check_valid_format(subs, params, fp)) continue; + r = snd_usb_endpoint_get_clock_rate(chip, fp->clock); + if (r > 0) { + if (!snd_interval_test(it, r)) + continue; + rmin = min(rmin, r); + rmax = max(rmax, r); + continue; + } if (fp->rate_table && fp->nr_rates) { for (i = 0; i < fp->nr_rates; i++) { r = fp->rate_table[i]; Patches currently in stable-queue which might be from tiwai@xxxxxxx are queue-5.15/alsa-usb-audio-rename-early_playback_start-flag-with-lowlatency_playback.patch queue-5.15/alsa-usb-audio-disable-low-latency-playback-for-free-wheel-mode.patch queue-5.15/alsa-usb-audio-avoid-killing-in-flight-urbs-during-draining.patch queue-5.15/alsa-usb-audio-less-restriction-for-low-latency-playback-mode.patch queue-5.15/alsa-usb-audio-improved-lowlatency-playback-support.patch queue-5.15/alsa-usb-audio-check-available-frames-for-the-next-packet-size.patch queue-5.15/alsa-usb-audio-switch-back-to-non-latency-mode-at-a-later-point.patch queue-5.15/alsa-usb-audio-fix-packet-size-calculation-regression.patch queue-5.15/alsa-usb-audio-don-t-start-stream-for-capture-at-prepare.patch queue-5.15/alsa-usb-audio-disable-low-latency-mode-for-implicit-feedback-sync.patch queue-5.15/alsa-usb-audio-add-spinlock-to-stop_urbs.patch queue-5.15/alsa-usb-audio-restrict-rates-for-the-shared-clocks.patch