mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-21 10:05:00 +08:00
1d0f953086
Commit16200948d8
("ALSA: usb-audio: Fix race at stopping the stream") was incomplete causing another more severe kernel panic, so it got reverted. This fixes both the original problem and its fallout kernel race/crash. The original fix is to move the endpoint member NULL clearing logic inside wait_clear_urbs() so the irq triggering the urb completion doesn't call retire_capture/playback_urb() after the NULL clearing and generate a panic. However this creates a new race between snd_usb_endpoint_start()'s call to wait_clear_urbs() and the irq urb completion handler which again calls retire_capture/playback_urb() leading to a new NULL dereference. We keep the EP deactivation code in snd_usb_endpoint_start() because removing it will break the EP reference counting (see [1] [2] for info), however we don't need the "can_sleep" mechanism anymore because a new function was introduced (snd_usb_endpoint_sync_pending_stop()) which synchronizes pending stops and gets called inside the pcm prepare callback. It also makes sense to remove can_sleep because it was also removed from deactivate_urbs() signature in [3] so we benefit from more simplification. [1] commit015618b90
("ALSA: snd-usb: Fix URB cancellation at stream start") [2] commite9ba389c5
("ALSA: usb-audio: Fix scheduling-while-atomic bug in PCM capture stream") [3] commitccc1696d5
("ALSA: usb-audio: simplify endpoint deactivation code") Fixes:f8114f8583
("Revert "ALSA: usb-audio: Fix race at stopping the stream"") Signed-off-by: Ioan-Adrian Ratiu <adi@adirat.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
37 lines
1.3 KiB
C
37 lines
1.3 KiB
C
#ifndef __USBAUDIO_ENDPOINT_H
|
|
#define __USBAUDIO_ENDPOINT_H
|
|
|
|
#define SND_USB_ENDPOINT_TYPE_DATA 0
|
|
#define SND_USB_ENDPOINT_TYPE_SYNC 1
|
|
|
|
struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
|
|
struct usb_host_interface *alts,
|
|
int ep_num, int direction, int type);
|
|
|
|
int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
|
|
snd_pcm_format_t pcm_format,
|
|
unsigned int channels,
|
|
unsigned int period_bytes,
|
|
unsigned int period_frames,
|
|
unsigned int buffer_periods,
|
|
unsigned int rate,
|
|
struct audioformat *fmt,
|
|
struct snd_usb_endpoint *sync_ep);
|
|
|
|
int snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
|
|
void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
|
|
void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
|
|
int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
|
|
void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
|
|
void snd_usb_endpoint_release(struct snd_usb_endpoint *ep);
|
|
void snd_usb_endpoint_free(struct snd_usb_endpoint *ep);
|
|
|
|
int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
|
|
int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);
|
|
|
|
void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
|
|
struct snd_usb_endpoint *sender,
|
|
const struct urb *urb);
|
|
|
|
#endif /* __USBAUDIO_ENDPOINT_H */
|