Revert "ALSA: usb-audio: Refcount multiple accesses on the single clock"

This reverts commit 9830e7383f which is
commit c11117b634 upstream.

It breaks the Android kernel abi and can be brought back in the future
in an abi-safe way if it is really needed.

Bug: 161946584
Change-Id: I118d9b1069bcc55b41a2353ecd4e00d42c301cec
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-05-16 10:20:23 +00:00
parent f41d29ad04
commit bff2c70560
4 changed files with 10 additions and 85 deletions

View File

@@ -645,7 +645,6 @@ static int snd_usb_audio_create(struct usb_interface *intf,
INIT_LIST_HEAD(&chip->pcm_list);
INIT_LIST_HEAD(&chip->ep_list);
INIT_LIST_HEAD(&chip->iface_ref_list);
INIT_LIST_HEAD(&chip->clock_ref_list);
INIT_LIST_HEAD(&chip->midi_list);
INIT_LIST_HEAD(&chip->mixer_list);

View File

@@ -46,7 +46,6 @@ struct audioformat {
struct snd_usb_substream;
struct snd_usb_iface_ref;
struct snd_usb_clock_ref;
struct snd_usb_endpoint;
struct snd_usb_power_domain;
@@ -65,7 +64,6 @@ struct snd_urb_ctx {
struct snd_usb_endpoint {
struct snd_usb_audio *chip;
struct snd_usb_iface_ref *iface_ref;
struct snd_usb_clock_ref *clock_ref;
int opened; /* open refcount; protect with chip->mutex */
atomic_t running; /* running status */
@@ -142,6 +140,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;

View File

@@ -37,14 +37,6 @@ struct snd_usb_iface_ref {
struct list_head list;
};
/* clock refcounting */
struct snd_usb_clock_ref {
unsigned char clock;
atomic_t locked;
int rate;
struct list_head list;
};
/*
* snd_usb_endpoint is a model that abstracts everything related to an
* USB endpoint and its streaming.
@@ -608,25 +600,6 @@ iface_ref_find(struct snd_usb_audio *chip, int iface)
return ip;
}
/* Similarly, a refcount object for clock */
static struct snd_usb_clock_ref *
clock_ref_find(struct snd_usb_audio *chip, int clock)
{
struct snd_usb_clock_ref *ref;
list_for_each_entry(ref, &chip->clock_ref_list, list)
if (ref->clock == clock)
return ref;
ref = kzalloc(sizeof(*ref), GFP_KERNEL);
if (!ref)
return NULL;
ref->clock = clock;
atomic_set(&ref->locked, 0);
list_add_tail(&ref->list, &chip->clock_ref_list);
return ref;
}
/*
* Get the existing endpoint object corresponding EP
* Returns NULL if not present.
@@ -804,14 +777,6 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
goto unlock;
}
if (fp->protocol != UAC_VERSION_1) {
ep->clock_ref = clock_ref_find(chip, fp->clock);
if (!ep->clock_ref) {
ep = NULL;
goto unlock;
}
}
ep->cur_audiofmt = fp;
ep->cur_channels = fp->channels;
ep->cur_rate = params_rate(params);
@@ -821,6 +786,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
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);
@@ -939,8 +905,8 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
ep->altsetting = 0;
ep->cur_audiofmt = NULL;
ep->cur_rate = 0;
ep->cur_clock = 0;
ep->iface_ref = NULL;
ep->clock_ref = NULL;
usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num);
}
mutex_unlock(&chip->mutex);
@@ -953,8 +919,6 @@ void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep)
ep->need_setup = true;
if (ep->iface_ref)
ep->iface_ref->need_setup = true;
if (ep->clock_ref)
ep->clock_ref->rate = 0;
}
/*
@@ -1361,33 +1325,6 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
return 0;
}
static int init_sample_rate(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
struct snd_usb_clock_ref *clock = ep->clock_ref;
int err;
if (clock) {
if (atomic_read(&clock->locked))
return 0;
if (clock->rate == ep->cur_rate)
return 0;
if (clock->rate && clock->rate != ep->cur_rate) {
usb_audio_dbg(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n",
clock->rate, ep->cur_rate, ep->ep_num);
return -EINVAL;
}
}
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate);
if (err < 0)
return err;
if (clock)
clock->rate = ep->cur_rate;
return 0;
}
/*
* snd_usb_endpoint_configure: Configure the endpoint
*
@@ -1417,7 +1354,8 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
* to update at each EP configuration
*/
if (ep->cur_audiofmt->protocol == UAC_VERSION_1) {
err = init_sample_rate(chip, ep);
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt,
ep->cur_rate);
if (err < 0)
goto unlock;
}
@@ -1447,7 +1385,7 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
if (err < 0)
goto unlock;
err = init_sample_rate(chip, ep);
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate);
if (err < 0)
goto unlock;
@@ -1481,15 +1419,15 @@ EXPORT_SYMBOL_GPL(snd_usb_endpoint_configure);
/* 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_clock_ref *ref;
struct snd_usb_endpoint *ep;
int rate = 0;
if (!clock)
return 0;
mutex_lock(&chip->mutex);
list_for_each_entry(ref, &chip->clock_ref_list, list) {
if (ref->clock == clock) {
rate = ref->rate;
list_for_each_entry(ep, &chip->ep_list, list) {
if (ep->cur_clock == clock && ep->cur_rate) {
rate = ep->cur_rate;
break;
}
}
@@ -1530,9 +1468,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
if (atomic_inc_return(&ep->running) != 1)
return 0;
if (ep->clock_ref)
atomic_inc(&ep->clock_ref->locked);
ep->active_mask = 0;
ep->unlink_mask = 0;
ep->phase = 0;
@@ -1644,9 +1579,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending)
if (ep->sync_source)
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;
trace_android_vh_audio_usb_offload_ep_action(ep, false);
}
@@ -1675,16 +1607,12 @@ void snd_usb_endpoint_free_all(struct snd_usb_audio *chip)
{
struct snd_usb_endpoint *ep, *en;
struct snd_usb_iface_ref *ip, *in;
struct snd_usb_clock_ref *cp, *cn;
list_for_each_entry_safe(ep, en, &chip->ep_list, list)
kfree(ep);
list_for_each_entry_safe(ip, in, &chip->iface_ref_list, list)
kfree(ip);
list_for_each_entry_safe(cp, cn, &chip->clock_ref_list, list)
kfree(ip);
}
/*

View File

@@ -48,7 +48,6 @@ struct snd_usb_audio {
struct list_head pcm_list; /* list of pcm streams */
struct list_head ep_list; /* list of audio-related endpoints */
struct list_head iface_ref_list; /* list of interface refcounts */
struct list_head clock_ref_list; /* list of clock refcounts */
int pcm_devs;
struct list_head midi_list; /* list of midi interfaces */