Commit efea7a57 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: usb-audio: Replace manual mutex/spinlock with guard()

This is another code cleanup by replacing the manual mutex or spinlock
with guard() macros.  usb_audio_disconnect() is slightly refactored
(split to another function) to apply guard() cleanly, but the rest are
rather straightforward conversions.

No functional changes but only code refactoring.

Link: https://patch.msgid.link/20250811082019.31052-1-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 6ff0d957
Loading
Loading
Loading
Loading
+22 −17
Original line number Diff line number Diff line
@@ -900,7 +900,7 @@ static int usb_audio_probe(struct usb_interface *intf,

	/* check whether it's already registered */
	chip = NULL;
	mutex_lock(&register_mutex);
	guard(mutex)(&register_mutex);
	for (i = 0; i < SNDRV_CARDS; i++) {
		if (usb_chip[i] && usb_chip[i]->dev == dev) {
			if (atomic_read(&usb_chip[i]->shutdown)) {
@@ -1015,7 +1015,6 @@ static int usb_audio_probe(struct usb_interface *intf,

	if (platform_ops && platform_ops->connect_cb)
		platform_ops->connect_cb(chip);
	mutex_unlock(&register_mutex);

	return 0;

@@ -1033,7 +1032,6 @@ static int usb_audio_probe(struct usb_interface *intf,
		if (!chip->num_interfaces)
			snd_card_free(chip->card);
	}
	mutex_unlock(&register_mutex);
	return err;
}

@@ -1041,18 +1039,14 @@ static int usb_audio_probe(struct usb_interface *intf,
 * we need to take care of counter, since disconnection can be called also
 * many times as well as usb_audio_probe().
 */
static void usb_audio_disconnect(struct usb_interface *intf)
static bool __usb_audio_disconnect(struct usb_interface *intf,
				   struct snd_usb_audio *chip,
				   struct snd_card *card)
{
	struct snd_usb_audio *chip = usb_get_intfdata(intf);
	struct snd_card *card;
	struct list_head *p;

	if (chip == USB_AUDIO_IFACE_UNUSED)
		return;

	card = chip->card;
	guard(mutex)(&register_mutex);

	mutex_lock(&register_mutex);
	if (platform_ops && platform_ops->disconnect_cb)
		platform_ops->disconnect_cb(chip);

@@ -1098,13 +1092,24 @@ static void usb_audio_disconnect(struct usb_interface *intf)
		usb_enable_autosuspend(interface_to_usbdev(intf));

	chip->num_interfaces--;
	if (chip->num_interfaces <= 0) {
	if (chip->num_interfaces > 0)
		return false;

	usb_chip[chip->index] = NULL;
		mutex_unlock(&register_mutex);
		snd_card_free_when_closed(card);
	} else {
		mutex_unlock(&register_mutex);
	return true;
}

static void usb_audio_disconnect(struct usb_interface *intf)
{
	struct snd_usb_audio *chip = usb_get_intfdata(intf);
	struct snd_card *card;

	if (chip == USB_AUDIO_IFACE_UNUSED)
		return;

	card = chip->card;
	if (__usb_audio_disconnect(intf, chip, card))
		snd_card_free_when_closed(card);
}

/* lock the shutdown (disconnect) task and autoresume */
+46 −78
Original line number Diff line number Diff line
@@ -163,22 +163,19 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep)
static int slave_next_packet_size(struct snd_usb_endpoint *ep,
				  unsigned int avail)
{
	unsigned long flags;
	unsigned int phase;
	int ret;

	if (ep->fill_max)
		return ep->maxframesize;

	spin_lock_irqsave(&ep->lock, flags);
	guard(spinlock_irqsave)(&ep->lock);
	phase = (ep->phase & 0xffff) + (ep->freqm << ep->datainterval);
	ret = min(phase >> 16, ep->maxframesize);
	if (avail && ret >= avail)
		ret = -EAGAIN;
	else
		ep->phase = phase;
	spin_unlock_irqrestore(&ep->lock, flags);

	return ret;
}

@@ -440,11 +437,8 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep)
static void push_back_to_ready_list(struct snd_usb_endpoint *ep,
				    struct snd_urb_ctx *ctx)
{
	unsigned long flags;

	spin_lock_irqsave(&ep->lock, flags);
	guard(spinlock_irqsave)(&ep->lock);
	list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
	spin_unlock_irqrestore(&ep->lock, flags);
}

/*
@@ -466,13 +460,11 @@ int snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
	bool implicit_fb = snd_usb_endpoint_implicit_feedback_sink(ep);

	while (ep_state_running(ep)) {

		unsigned long flags;
		struct snd_usb_packet_info *packet;
		struct snd_urb_ctx *ctx = NULL;
		int err, i;

		spin_lock_irqsave(&ep->lock, flags);
		scoped_guard(spinlock_irqsave, &ep->lock) {
			if ((!implicit_fb || ep->next_packet_queued > 0) &&
			    !list_empty(&ep->ready_playback_urbs)) {
				/* take URB out of FIFO */
@@ -482,7 +474,7 @@ int snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
				if (implicit_fb)
					packet = next_packet_fifo_dequeue(ep);
			}
		spin_unlock_irqrestore(&ep->lock, flags);
		}

		if (ctx == NULL)
			break;
@@ -768,12 +760,8 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
				 const struct audioformat *fp,
				 const struct snd_pcm_hw_params *params)
{
	bool ret;

	mutex_lock(&chip->mutex);
	ret = endpoint_compatible(ep, fp, params);
	mutex_unlock(&chip->mutex);
	return ret;
	guard(mutex)(&chip->mutex);
	return endpoint_compatible(ep, fp, params);
}

/*
@@ -799,11 +787,11 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
	struct snd_usb_endpoint *ep;
	int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint;

	mutex_lock(&chip->mutex);
	guard(mutex)(&chip->mutex);
	ep = snd_usb_get_endpoint(chip, ep_num);
	if (!ep) {
		usb_audio_err(chip, "Cannot find EP 0x%x to open\n", ep_num);
		goto unlock;
		return NULL;
	}

	if (!ep->opened) {
@@ -820,17 +808,13 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
			      ep_num, ep->iface, ep->altsetting, ep->ep_idx);

		ep->iface_ref = iface_ref_find(chip, ep->iface);
		if (!ep->iface_ref) {
			ep = NULL;
			goto unlock;
		}
		if (!ep->iface_ref)
			return NULL;

		if (fp->protocol != UAC_VERSION_1) {
			ep->clock_ref = clock_ref_find(chip, fp->clock);
			if (!ep->clock_ref) {
				ep = NULL;
				goto unlock;
			}
			if (!ep->clock_ref)
				return NULL;
			ep->clock_ref->opened++;
		}

@@ -859,16 +843,13 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
			      ep->implicit_fb_sync);

	} else {
		if (WARN_ON(!ep->iface_ref)) {
			ep = NULL;
			goto unlock;
		}
		if (WARN_ON(!ep->iface_ref))
			return NULL;

		if (!endpoint_compatible(ep, fp, params)) {
			usb_audio_err(chip, "Incompatible EP setup for 0x%x\n",
				      ep_num);
			ep = NULL;
			goto unlock;
			return NULL;
		}

		usb_audio_dbg(chip, "Reopened EP 0x%x (count %d)\n",
@@ -879,9 +860,6 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
		ep->iface_ref->need_setup = true;

	ep->opened++;

 unlock:
	mutex_unlock(&chip->mutex);
	return ep;
}

@@ -964,7 +942,7 @@ static int endpoint_set_interface(struct snd_usb_audio *chip,
void snd_usb_endpoint_close(struct snd_usb_audio *chip,
			    struct snd_usb_endpoint *ep)
{
	mutex_lock(&chip->mutex);
	guard(mutex)(&chip->mutex);
	usb_audio_dbg(chip, "Closing EP 0x%x (count %d)\n",
		      ep->ep_num, ep->opened);

@@ -985,7 +963,6 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
		ep->clock_ref = NULL;
		usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num);
	}
	mutex_unlock(&chip->mutex);
}

/* Prepare for suspening EP, called from the main suspend handler */
@@ -1047,7 +1024,6 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
static int stop_urbs(struct snd_usb_endpoint *ep, bool force, bool keep_pending)
{
	unsigned int i;
	unsigned long flags;

	if (!force && atomic_read(&ep->running))
		return -EBUSY;
@@ -1055,11 +1031,11 @@ static int stop_urbs(struct snd_usb_endpoint *ep, bool force, bool keep_pending)
	if (!ep_state_update(ep, EP_STATE_RUNNING, EP_STATE_STOPPING))
		return 0;

	spin_lock_irqsave(&ep->lock, flags);
	scoped_guard(spinlock_irqsave, &ep->lock) {
		INIT_LIST_HEAD(&ep->ready_playback_urbs);
		ep->next_packet_head = 0;
		ep->next_packet_queued = 0;
	spin_unlock_irqrestore(&ep->lock, flags);
	}

	if (keep_pending)
		return 0;
@@ -1360,16 +1336,16 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
				struct snd_usb_endpoint *ep)
{
	const struct audioformat *fmt = ep->cur_audiofmt;
	int err = 0;
	int err;

	mutex_lock(&chip->mutex);
	guard(mutex)(&chip->mutex);
	if (!ep->need_setup)
		goto unlock;
		return 0;

	/* release old buffers, if any */
	err = release_urbs(ep, false);
	if (err < 0)
		goto unlock;
		return err;

	ep->datainterval = fmt->datainterval;
	ep->maxpacksize = fmt->maxpacksize;
@@ -1407,7 +1383,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
	usb_audio_dbg(chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err);

	if (err < 0)
		goto unlock;
		return err;

	/* some unit conversions in runtime */
	ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes;
@@ -1419,8 +1395,6 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
		err = 0;
	}

 unlock:
	mutex_unlock(&chip->mutex);
	return err;
}

@@ -1467,11 +1441,11 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
	bool iface_first;
	int err = 0;

	mutex_lock(&chip->mutex);
	guard(mutex)(&chip->mutex);
	if (WARN_ON(!ep->iface_ref))
		goto unlock;
		return 0;
	if (!ep->need_prepare)
		goto unlock;
		return 0;

	/* If the interface has been already set up, just set EP parameters */
	if (!ep->iface_ref->need_setup) {
@@ -1481,7 +1455,7 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
		if (ep->cur_audiofmt->protocol == UAC_VERSION_1) {
			err = init_sample_rate(chip, ep);
			if (err < 0)
				goto unlock;
				return err;
		}
		goto done;
	}
@@ -1499,37 +1473,33 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
	if (iface_first) {
		err = endpoint_set_interface(chip, ep, true);
		if (err < 0)
			goto unlock;
			return err;
	}

	err = snd_usb_init_pitch(chip, ep->cur_audiofmt);
	if (err < 0)
		goto unlock;
		return err;

	err = init_sample_rate(chip, ep);
	if (err < 0)
		goto unlock;
		return err;

	err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
	if (err < 0)
		goto unlock;
		return err;

	/* for UAC2/3, enable the interface altset here at last */
	if (!iface_first) {
		err = endpoint_set_interface(chip, ep, true);
		if (err < 0)
			goto unlock;
			return err;
	}

	ep->iface_ref->need_setup = false;

 done:
	ep->need_prepare = false;
	err = 1;

unlock:
	mutex_unlock(&chip->mutex);
	return err;
	return 1;
}
EXPORT_SYMBOL_GPL(snd_usb_endpoint_prepare);

@@ -1541,14 +1511,13 @@ int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock)

	if (!clock)
		return 0;
	mutex_lock(&chip->mutex);
	guard(mutex)(&chip->mutex);
	list_for_each_entry(ref, &chip->clock_ref_list, list) {
		if (ref->clock == clock) {
			rate = ref->rate;
			break;
		}
	}
	mutex_unlock(&chip->mutex);
	return rate;
}

@@ -1898,9 +1867,8 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
		 * If the frequency looks valid, set it.
		 * This value is referred to in prepare_playback_urb().
		 */
		spin_lock_irqsave(&ep->lock, flags);
		guard(spinlock_irqsave)(&ep->lock);
		ep->freqm = f;
		spin_unlock_irqrestore(&ep->lock, flags);
	} else {
		/*
		 * Out of range; maybe the shift value is wrong.
+2 −4
Original line number Diff line number Diff line
@@ -140,11 +140,10 @@ int snd_media_start_pipeline(struct snd_usb_substream *subs)
	if (!mctl)
		return 0;

	mutex_lock(&mctl->media_dev->graph_mutex);
	guard(mutex)(&mctl->media_dev->graph_mutex);
	if (mctl->media_dev->enable_source)
		ret = mctl->media_dev->enable_source(&mctl->media_entity,
						     &mctl->media_pipe);
	mutex_unlock(&mctl->media_dev->graph_mutex);
	return ret;
}

@@ -155,10 +154,9 @@ void snd_media_stop_pipeline(struct snd_usb_substream *subs)
	if (!mctl)
		return;

	mutex_lock(&mctl->media_dev->graph_mutex);
	guard(mutex)(&mctl->media_dev->graph_mutex);
	if (mctl->media_dev->disable_source)
		mctl->media_dev->disable_source(&mctl->media_entity);
	mutex_unlock(&mctl->media_dev->graph_mutex);
}

static int snd_media_mixer_init(struct snd_usb_audio *chip)
+26 −42
Original line number Diff line number Diff line
@@ -265,16 +265,15 @@ static void snd_usbmidi_out_urb_complete(struct urb *urb)
	struct out_urb_context *context = urb->context;
	struct snd_usb_midi_out_endpoint *ep = context->ep;
	unsigned int urb_index;
	unsigned long flags;

	spin_lock_irqsave(&ep->buffer_lock, flags);
	scoped_guard(spinlock_irqsave, &ep->buffer_lock) {
		urb_index = context - ep->urbs;
		ep->active_urbs &= ~(1 << urb_index);
		if (unlikely(ep->drain_urbs)) {
			ep->drain_urbs &= ~(1 << urb_index);
			wake_up(&ep->drain_wait);
		}
	spin_unlock_irqrestore(&ep->buffer_lock, flags);
	}
	if (urb->status < 0) {
		int err = snd_usbmidi_urb_error(urb);
		if (err < 0) {
@@ -295,13 +294,10 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep)
{
	unsigned int urb_index;
	struct urb *urb;
	unsigned long flags;

	spin_lock_irqsave(&ep->buffer_lock, flags);
	if (ep->umidi->disconnected) {
		spin_unlock_irqrestore(&ep->buffer_lock, flags);
	guard(spinlock_irqsave)(&ep->buffer_lock);
	if (ep->umidi->disconnected)
		return;
	}

	urb_index = ep->next_urb;
	for (;;) {
@@ -325,7 +321,6 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep)
			break;
	}
	ep->next_urb = urb_index;
	spin_unlock_irqrestore(&ep->buffer_lock, flags);
}

static void snd_usbmidi_out_work(struct work_struct *work)
@@ -342,9 +337,8 @@ static void snd_usbmidi_error_timer(struct timer_list *t)
	struct snd_usb_midi *umidi = timer_container_of(umidi, t, error_timer);
	unsigned int i, j;

	spin_lock(&umidi->disc_lock);
	guard(spinlock)(&umidi->disc_lock);
	if (umidi->disconnected) {
		spin_unlock(&umidi->disc_lock);
		return;
	}
	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
@@ -361,7 +355,6 @@ static void snd_usbmidi_error_timer(struct timer_list *t)
		if (umidi->endpoints[i].out)
			snd_usbmidi_do_output(umidi->endpoints[i].out);
	}
	spin_unlock(&umidi->disc_lock);
}

/* helper function to send static data that may not DMA-able */
@@ -1148,13 +1141,11 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir,
	struct snd_usb_midi *umidi = substream->rmidi->private_data;
	struct snd_kcontrol *ctl;

	down_read(&umidi->disc_rwsem);
	if (umidi->disconnected) {
		up_read(&umidi->disc_rwsem);
	guard(rwsem_read)(&umidi->disc_rwsem);
	if (umidi->disconnected)
		return open ? -ENODEV : 0;
	}

	mutex_lock(&umidi->mutex);
	guard(mutex)(&umidi->mutex);
	if (open) {
		if (!umidi->opened[0] && !umidi->opened[1]) {
			if (umidi->roland_load_ctl) {
@@ -1183,8 +1174,6 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir,
			}
		}
	}
	mutex_unlock(&umidi->mutex);
	up_read(&umidi->disc_rwsem);
	return 0;
}

@@ -1548,11 +1537,10 @@ void snd_usbmidi_disconnect(struct list_head *p)
	 * a timer may submit an URB. To reliably break the cycle
	 * a flag under lock must be used
	 */
	down_write(&umidi->disc_rwsem);
	spin_lock_irq(&umidi->disc_lock);
	scoped_guard(rwsem_write, &umidi->disc_rwsem) {
		guard(spinlock_irq)(&umidi->disc_lock);
		umidi->disconnected = 1;
	spin_unlock_irq(&umidi->disc_lock);
	up_write(&umidi->disc_rwsem);
	}

	timer_shutdown_sync(&umidi->error_timer);

@@ -2094,11 +2082,10 @@ static int roland_load_put(struct snd_kcontrol *kcontrol,

	if (value->value.enumerated.item[0] > 1)
		return -EINVAL;
	mutex_lock(&umidi->mutex);
	guard(mutex)(&umidi->mutex);
	changed = value->value.enumerated.item[0] != kcontrol->private_value;
	if (changed)
		kcontrol->private_value = value->value.enumerated.item[0];
	mutex_unlock(&umidi->mutex);
	return changed;
}

@@ -2448,18 +2435,17 @@ static void snd_usbmidi_input_start_ep(struct snd_usb_midi *umidi,
				       struct snd_usb_midi_in_endpoint *ep)
{
	unsigned int i;
	unsigned long flags;

	if (!ep)
		return;
	for (i = 0; i < INPUT_URBS; ++i) {
		struct urb *urb = ep->urbs[i];
		spin_lock_irqsave(&umidi->disc_lock, flags);
		scoped_guard(spinlock_irqsave, &umidi->disc_lock) {
			if (!atomic_read(&urb->use_count)) {
				urb->dev = ep->umidi->dev;
				snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
			}
		spin_unlock_irqrestore(&umidi->disc_lock, flags);
		}
	}
}

@@ -2488,9 +2474,8 @@ void snd_usbmidi_suspend(struct list_head *p)
	struct snd_usb_midi *umidi;

	umidi = list_entry(p, struct snd_usb_midi, list);
	mutex_lock(&umidi->mutex);
	guard(mutex)(&umidi->mutex);
	snd_usbmidi_input_stop(p);
	mutex_unlock(&umidi->mutex);
}
EXPORT_SYMBOL(snd_usbmidi_suspend);

@@ -2502,9 +2487,8 @@ void snd_usbmidi_resume(struct list_head *p)
	struct snd_usb_midi *umidi;

	umidi = list_entry(p, struct snd_usb_midi, list);
	mutex_lock(&umidi->mutex);
	guard(mutex)(&umidi->mutex);
	snd_usbmidi_input_start(p);
	mutex_unlock(&umidi->mutex);
}
EXPORT_SYMBOL(snd_usbmidi_resume);

+4 −12
Original line number Diff line number Diff line
@@ -160,15 +160,13 @@ static void output_urb_complete(struct urb *urb)
{
	struct snd_usb_midi2_urb *ctx = urb->context;
	struct snd_usb_midi2_endpoint *ep = ctx->ep;
	unsigned long flags;

	spin_lock_irqsave(&ep->lock, flags);
	guard(spinlock_irqsave)(&ep->lock);
	set_bit(ctx->index, &ep->urb_free);
	if (urb->status >= 0 && atomic_read(&ep->running))
		submit_output_urbs_locked(ep);
	if (ep->urb_free == ep->urb_free_mask)
		wake_up(&ep->wait);
	spin_unlock_irqrestore(&ep->lock, flags);
}

/* prepare for input submission: just set the buffer length */
@@ -189,10 +187,9 @@ static void input_urb_complete(struct urb *urb)
{
	struct snd_usb_midi2_urb *ctx = urb->context;
	struct snd_usb_midi2_endpoint *ep = ctx->ep;
	unsigned long flags;
	int len;

	spin_lock_irqsave(&ep->lock, flags);
	guard(spinlock_irqsave)(&ep->lock);
	if (ep->disconnected || urb->status < 0)
		goto dequeue;
	len = urb->actual_length;
@@ -208,22 +205,18 @@ static void input_urb_complete(struct urb *urb)
	submit_input_urbs_locked(ep);
	if (ep->urb_free == ep->urb_free_mask)
		wake_up(&ep->wait);
	spin_unlock_irqrestore(&ep->lock, flags);
}

/* URB submission helper; for both direction */
static void submit_io_urbs(struct snd_usb_midi2_endpoint *ep)
{
	unsigned long flags;

	if (!ep)
		return;
	spin_lock_irqsave(&ep->lock, flags);
	guard(spinlock_irqsave)(&ep->lock);
	if (ep->direction == STR_IN)
		submit_input_urbs_locked(ep);
	else
		submit_output_urbs_locked(ep);
	spin_unlock_irqrestore(&ep->lock, flags);
}

/* kill URBs for close, suspend and disconnect */
@@ -248,13 +241,12 @@ static void drain_urb_queue(struct snd_usb_midi2_endpoint *ep)
{
	if (!ep)
		return;
	spin_lock_irq(&ep->lock);
	guard(spinlock_irq)(&ep->lock);
	atomic_set(&ep->running, 0);
	wait_event_lock_irq_timeout(ep->wait,
				    ep->disconnected ||
				    ep->urb_free == ep->urb_free_mask,
				    ep->lock, msecs_to_jiffies(500));
	spin_unlock_irq(&ep->lock);
}

/* release URBs for an EP */
Loading