]> 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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 Oct 2022 07:57:21 +0000 (09:57 +0200)
[ 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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
sound/usb/endpoint.c

index 7a7f5ebafe4aa39a8ea06cadeeea5ef71172e2ce..118b1fb7dc86ce8278ce12386f07df420c982d89 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;
        struct list_head list;
 };
@@ -802,6 +803,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
                                ep = NULL;
                                goto unlock;
                        }
+                       ep->clock_ref->opened++;
                }
 
                ep->cur_audiofmt = fp;
@@ -925,8 +927,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;
@@ -1633,8 +1637,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);
        }
 }