usb: gadget: Fix synchronization issue between f_audio_source
Race is happening when both audio_pcm_close() and audio_send() executes in parallel. When the PCM session is closed, the substream attribute of the audio_dev structure is set to NULL in audio_pcm_close(). As there is no synchronization protection for the audio_dev subtream attributes in audio_send(), it is causing NULL pointer dereference. Hence fixing the issue by adding proper synchronization protection for the audio_dev subtream attributes in audio_send(). CRs-Fixed: 613498 Change-Id: Id9ab0d4e347b8bb2f551f9033829e541bdcaf0e8 Signed-off-by: ChandanaKishori Chiluveru <cchilu@codeaurora.org> Signed-off-by: Tarun Gupta <tarung@codeaurora.org>
This commit is contained in:
parent
c5685ec0f3
commit
a510e932e4
1 changed files with 24 additions and 3 deletions
|
@ -369,15 +369,22 @@ static void audio_send(struct audio_dev *audio)
|
|||
s64 msecs;
|
||||
s64 frames;
|
||||
ktime_t now;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&audio->lock, flags);
|
||||
/* audio->substream will be null if we have been closed */
|
||||
if (!audio->substream)
|
||||
if (!audio->substream) {
|
||||
spin_unlock_irqrestore(&audio->lock, flags);
|
||||
return;
|
||||
}
|
||||
/* audio->buffer_pos will be null if we have been stopped */
|
||||
if (!audio->buffer_pos)
|
||||
if (!audio->buffer_pos) {
|
||||
spin_unlock_irqrestore(&audio->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
runtime = audio->substream->runtime;
|
||||
spin_unlock_irqrestore(&audio->lock, flags);
|
||||
|
||||
/* compute number of frames to send */
|
||||
now = ktime_get();
|
||||
|
@ -400,8 +407,21 @@ static void audio_send(struct audio_dev *audio)
|
|||
|
||||
while (frames > 0) {
|
||||
req = audio_req_get(audio);
|
||||
if (!req)
|
||||
spin_lock_irqsave(&audio->lock, flags);
|
||||
/* audio->substream will be null if we have been closed */
|
||||
if (!audio->substream) {
|
||||
spin_unlock_irqrestore(&audio->lock, flags);
|
||||
return;
|
||||
}
|
||||
/* audio->buffer_pos will be null if we have been stopped */
|
||||
if (!audio->buffer_pos) {
|
||||
spin_unlock_irqrestore(&audio->lock, flags);
|
||||
return;
|
||||
}
|
||||
if (!req) {
|
||||
spin_unlock_irqrestore(&audio->lock, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
length = frames_to_bytes(runtime, frames);
|
||||
if (length > IN_EP_MAX_PACKET_SIZE)
|
||||
|
@ -427,6 +447,7 @@ static void audio_send(struct audio_dev *audio)
|
|||
}
|
||||
|
||||
req->length = length;
|
||||
spin_unlock_irqrestore(&audio->lock, flags);
|
||||
ret = usb_ep_queue(audio->in_ep, req, GFP_ATOMIC);
|
||||
if (ret < 0) {
|
||||
pr_err("usb_ep_queue failed ret: %d\n", ret);
|
||||
|
|
Loading…
Add table
Reference in a new issue