mirror of
https://github.com/torvalds/linux.git
synced 2024-11-14 08:02:07 +00:00
ALSA: usb-audio: Refactoring endpoint URB deactivation
Minor code refactoring to consolidate the URB deactivation code in endpoint.c. A slight behavior change is that the error handling in snd_usb_endpoint_start() leaves EP_FLAG_STOPPING now. This should be synced with the later PCM sync_stop callback. Tested-by: Keith Milner <kamilner@superlative.org> Tested-by: Dylan Robinson <dylan_robinson@motu.com> Link: https://lore.kernel.org/r/20201123085347.19667-30-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
43b81e8406
commit
d0f09d1e4a
@ -777,6 +777,9 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
|
|||||||
unsigned long end_time = jiffies + msecs_to_jiffies(1000);
|
unsigned long end_time = jiffies + msecs_to_jiffies(1000);
|
||||||
int alive;
|
int alive;
|
||||||
|
|
||||||
|
if (!test_bit(EP_FLAG_STOPPING, &ep->flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
alive = bitmap_weight(&ep->active_mask, ep->nurbs);
|
alive = bitmap_weight(&ep->active_mask, ep->nurbs);
|
||||||
if (!alive)
|
if (!alive)
|
||||||
@ -802,22 +805,31 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
|
|||||||
*/
|
*/
|
||||||
void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
|
void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
|
||||||
{
|
{
|
||||||
if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags))
|
if (ep)
|
||||||
wait_clear_urbs(ep);
|
wait_clear_urbs(ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* unlink active urbs.
|
* Stop and unlink active urbs.
|
||||||
|
*
|
||||||
|
* This function checks and clears EP_FLAG_RUNNING state.
|
||||||
|
* When @wait_sync is set, it waits until all pending URBs are killed.
|
||||||
*/
|
*/
|
||||||
static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force)
|
static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force,
|
||||||
|
bool wait_sync)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */
|
if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
|
|
||||||
clear_bit(EP_FLAG_RUNNING, &ep->flags);
|
if (atomic_read(&ep->running))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
if (!test_and_clear_bit(EP_FLAG_RUNNING, &ep->flags))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
set_bit(EP_FLAG_STOPPING, &ep->flags);
|
||||||
INIT_LIST_HEAD(&ep->ready_playback_urbs);
|
INIT_LIST_HEAD(&ep->ready_playback_urbs);
|
||||||
ep->next_packet_head = 0;
|
ep->next_packet_head = 0;
|
||||||
ep->next_packet_queued = 0;
|
ep->next_packet_queued = 0;
|
||||||
@ -831,6 +843,9 @@ static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (wait_sync)
|
||||||
|
return wait_clear_urbs(ep);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,8 +860,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
|
|||||||
snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
|
snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
|
||||||
|
|
||||||
/* stop urbs */
|
/* stop urbs */
|
||||||
deactivate_urbs(ep, force);
|
stop_and_unlink_urbs(ep, force, true);
|
||||||
wait_clear_urbs(ep);
|
|
||||||
|
|
||||||
for (i = 0; i < ep->nurbs; i++)
|
for (i = 0; i < ep->nurbs; i++)
|
||||||
release_urb_ctx(&ep->urb[i]);
|
release_urb_ctx(&ep->urb[i]);
|
||||||
@ -1261,9 +1275,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
|
|||||||
if (atomic_inc_return(&ep->running) != 1)
|
if (atomic_inc_return(&ep->running) != 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* just to be sure */
|
|
||||||
deactivate_urbs(ep, false);
|
|
||||||
|
|
||||||
ep->active_mask = 0;
|
ep->active_mask = 0;
|
||||||
ep->unlink_mask = 0;
|
ep->unlink_mask = 0;
|
||||||
ep->phase = 0;
|
ep->phase = 0;
|
||||||
@ -1317,11 +1328,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
__error:
|
__error:
|
||||||
if (ep->sync_master)
|
snd_usb_endpoint_stop(ep);
|
||||||
WRITE_ONCE(ep->sync_master->sync_slave, NULL);
|
|
||||||
clear_bit(EP_FLAG_RUNNING, &ep->flags);
|
|
||||||
atomic_dec(&ep->running);
|
|
||||||
deactivate_urbs(ep, false);
|
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1354,10 +1361,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
|
|||||||
if (ep->sync_master)
|
if (ep->sync_master)
|
||||||
WRITE_ONCE(ep->sync_master->sync_slave, NULL);
|
WRITE_ONCE(ep->sync_master->sync_slave, NULL);
|
||||||
|
|
||||||
if (!atomic_dec_return(&ep->running)) {
|
if (!atomic_dec_return(&ep->running))
|
||||||
deactivate_urbs(ep, false);
|
stop_and_unlink_urbs(ep, false, false);
|
||||||
set_bit(EP_FLAG_STOPPING, &ep->flags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user