mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-30 22:26:55 +00:00
ALSA: usb-audio: Properly refcounting clock rate
[ Upstream commit9a737e7f8b
] We fixed the bug introduced by the patch for managing the shared clocks at the commit809f44a0cc
("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:809f44a0cc
("ALSA: usb-audio: Clear fixed clock rate at closing EP") Fixes:c11117b634
("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>
This commit is contained in:
parent
811522ac56
commit
71f43a9c59
1 changed files with 7 additions and 4 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue