]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ALSA: usb-audio: Properly refcounting clock rate
authorTakashi Iwai <tiwai@suse.de>
Tue, 20 Sep 2022 18:11:26 +0000 (20:11 +0200)
committerSasha Levin <sashal@kernel.org>
Fri, 15 Mar 2024 14:48:18 +0000 (10:48 -0400)
[ Upstream commit 9a737e7f8b371e97eb649904276407cee2c9cf30 ]

We fixed the bug introduced by the patch for managing the shared
clocks at the commit 809f44a0cc5a ("ALSA: usb-audio: Clear fixed clock
rate at closing EP"), but it was merely a workaround.  By this change,
the clock reference rate is cleared at each EP close, hence the still
remaining EP may need a re-setup of rate unnecessarily.

This patch introduces the proper refcounting for the clock reference
object so that the clock setup is done only when needed.

Fixes: 809f44a0cc5a ("ALSA: usb-audio: Clear fixed clock rate at closing EP")
Fixes: c11117b634f4 ("ALSA: usb-audio: Refcount multiple accesses on the single clock")
Link: https://lore.kernel.org/r/20220920181126.4912-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
Signed-off-by: Sasha Levin <sashal@kernel.org>
sound/usb/endpoint.c

index 32a9e016665c823820fbf43ec569f2eb5c08ac38..2d3f814d067b5116aa762a0a6be51e8ccecfd041 100644 (file)
@@ -39,6 +39,7 @@ struct snd_usb_iface_ref {
 struct snd_usb_clock_ref {
        unsigned char clock;
        atomic_t locked;
+       int opened;
        int rate;
        bool need_setup;
        struct list_head list;
@@ -810,6 +811,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
                                ep = NULL;
                                goto unlock;
                        }
+                       ep->clock_ref->opened++;
                }
 
                ep->cur_audiofmt = fp;
@@ -934,8 +936,10 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
                endpoint_set_interface(chip, ep, false);
 
        if (!--ep->opened) {
-               if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked))
-                       ep->clock_ref->rate = 0;
+               if (ep->clock_ref) {
+                       if (!--ep->clock_ref->opened)
+                               ep->clock_ref->rate = 0;
+               }
                ep->iface = 0;
                ep->altsetting = 0;
                ep->cur_audiofmt = NULL;
@@ -1656,8 +1660,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending)
                        WRITE_ONCE(ep->sync_source->sync_sink, NULL);
                stop_urbs(ep, false, keep_pending);
                if (ep->clock_ref)
-                       if (!atomic_dec_return(&ep->clock_ref->locked))
-                               ep->clock_ref->rate = 0;
+                       atomic_dec(&ep->clock_ref->locked);
        }
 }