when usb audio device removes, it doesn't notify the ALSA read / write thread. due to no data transmitting any more, those threads wait for a long timeout(10s), then detects IO error. it causes long time blocking in upper layer read/write. to fix this issue, wake up potential sleep thread if necessary when audio unbind. substream & pcm may still be used after audio unbind, and we should only set null to it in audio_pcm_close. Signed-off-by: Qiao Zhou <zhouqiao@xxxxxxxxxxx> --- drivers/usb/gadget/f_audio_source.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/f_audio_source.c b/drivers/usb/gadget/f_audio_source.c index c757409..2909427 100644 --- a/drivers/usb/gadget/f_audio_source.c +++ b/drivers/usb/gadget/f_audio_source.c @@ -620,15 +620,22 @@ static void audio_unbind(struct usb_configuration *c, struct usb_function *f) { struct audio_dev *audio = func_to_audio(f); + struct snd_pcm_substream *substream = audio->substream; struct usb_request *req; while ((req = audio_req_get(audio))) audio_request_free(req, audio->in_ep); + /* + * wake up potential sleep thread if necessary, and to timely + * notify ALSA write thread so that it doesn't need to wait for + * the 10s timeout. + */ + if (substream && substream->runtime && substream->runtime->twake) + wake_up(&substream->runtime->tsleep); + snd_card_free_when_closed(audio->card); audio->card = NULL; - audio->pcm = NULL; - audio->substream = NULL; audio->in_ep = NULL; } @@ -670,6 +677,7 @@ static int audio_pcm_close(struct snd_pcm_substream *substream) unsigned long flags; spin_lock_irqsave(&audio->lock, flags); + audio->pcm = NULL; audio->substream = NULL; spin_unlock_irqrestore(&audio->lock, flags); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html