Skip to content

Commit c7d1868

Browse files
Vladimir Zapolskiygregkh
authored andcommitted
usb: gadget: u_audio: remove cached period bytes value
[ Upstream commit 773e53d ] Substream period size potentially can be changed in runtime, however this is not accounted in the data copying routine, the change replaces the cached value with an actual value from substream runtime. As a side effect the change also removes a potential division by zero in u_audio_iso_complete() function, if there is a race with uac_pcm_hw_free(), which sets prm->period_size to 0. Fixes: 132fcb4 ("usb: gadget: Add Audio Class 2.0 Driver") Signed-off-by: Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com> Signed-off-by: Eugeniu Rosca <erosca@de.adit-jv.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 42b09be commit c7d1868

File tree

1 file changed

+5
-35
lines changed

1 file changed

+5
-35
lines changed

drivers/usb/gadget/function/u_audio.c

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ struct uac_rtd_params {
4949

5050
void *rbuf;
5151

52-
size_t period_size;
53-
5452
unsigned max_psize; /* MaxPacketSize of endpoint */
5553
struct uac_req *ureq;
5654

@@ -92,7 +90,6 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
9290
unsigned pending;
9391
unsigned long flags;
9492
unsigned int hw_ptr;
95-
bool update_alsa = false;
9693
int status = req->status;
9794
struct uac_req *ur = req->context;
9895
struct snd_pcm_substream *substream;
@@ -145,11 +142,6 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
145142
req->actual = req->length;
146143
}
147144

148-
pending = prm->hw_ptr % prm->period_size;
149-
pending += req->actual;
150-
if (pending >= prm->period_size)
151-
update_alsa = true;
152-
153145
hw_ptr = prm->hw_ptr;
154146

155147
spin_unlock_irqrestore(&prm->lock, flags);
@@ -180,14 +172,15 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
180172
spin_lock_irqsave(&prm->lock, flags);
181173
/* update hw_ptr after data is copied to memory */
182174
prm->hw_ptr = (hw_ptr + req->actual) % runtime->dma_bytes;
175+
hw_ptr = prm->hw_ptr;
183176
spin_unlock_irqrestore(&prm->lock, flags);
184177

178+
if ((hw_ptr % snd_pcm_lib_period_bytes(substream)) < req->actual)
179+
snd_pcm_period_elapsed(substream);
180+
185181
exit:
186182
if (usb_ep_queue(ep, req, GFP_ATOMIC))
187183
dev_err(uac->card->dev, "%d Error!\n", __LINE__);
188-
189-
if (update_alsa)
190-
snd_pcm_period_elapsed(substream);
191184
}
192185

193186
static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -250,35 +243,12 @@ static snd_pcm_uframes_t uac_pcm_pointer(struct snd_pcm_substream *substream)
250243
static int uac_pcm_hw_params(struct snd_pcm_substream *substream,
251244
struct snd_pcm_hw_params *hw_params)
252245
{
253-
struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
254-
struct uac_rtd_params *prm;
255-
int err;
256-
257-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
258-
prm = &uac->p_prm;
259-
else
260-
prm = &uac->c_prm;
261-
262-
err = snd_pcm_lib_malloc_pages(substream,
246+
return snd_pcm_lib_malloc_pages(substream,
263247
params_buffer_bytes(hw_params));
264-
if (err >= 0)
265-
prm->period_size = params_period_bytes(hw_params);
266-
267-
return err;
268248
}
269249

270250
static int uac_pcm_hw_free(struct snd_pcm_substream *substream)
271251
{
272-
struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
273-
struct uac_rtd_params *prm;
274-
275-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
276-
prm = &uac->p_prm;
277-
else
278-
prm = &uac->c_prm;
279-
280-
prm->period_size = 0;
281-
282252
return snd_pcm_lib_free_pages(substream);
283253
}
284254

0 commit comments

Comments
 (0)