Skip to content

Commit 773e53d

Browse files
Vladimir ZapolskiyFelipe Balbi
Vladimir Zapolskiy
authored and
Felipe Balbi
committed
usb: gadget: u_audio: remove cached period bytes value
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 <[email protected]> Signed-off-by: Eugeniu Rosca <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent 96afb54 commit 773e53d

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
@@ -40,8 +40,6 @@ struct uac_rtd_params {
4040

4141
void *rbuf;
4242

43-
size_t period_size;
44-
4543
unsigned max_psize; /* MaxPacketSize of endpoint */
4644
struct uac_req *ureq;
4745

@@ -83,7 +81,6 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
8381
unsigned pending;
8482
unsigned long flags;
8583
unsigned int hw_ptr;
86-
bool update_alsa = false;
8784
int status = req->status;
8885
struct uac_req *ur = req->context;
8986
struct snd_pcm_substream *substream;
@@ -136,11 +133,6 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
136133
req->actual = req->length;
137134
}
138135

139-
pending = prm->hw_ptr % prm->period_size;
140-
pending += req->actual;
141-
if (pending >= prm->period_size)
142-
update_alsa = true;
143-
144136
hw_ptr = prm->hw_ptr;
145137

146138
spin_unlock_irqrestore(&prm->lock, flags);
@@ -171,14 +163,15 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
171163
spin_lock_irqsave(&prm->lock, flags);
172164
/* update hw_ptr after data is copied to memory */
173165
prm->hw_ptr = (hw_ptr + req->actual) % runtime->dma_bytes;
166+
hw_ptr = prm->hw_ptr;
174167
spin_unlock_irqrestore(&prm->lock, flags);
175168

169+
if ((hw_ptr % snd_pcm_lib_period_bytes(substream)) < req->actual)
170+
snd_pcm_period_elapsed(substream);
171+
176172
exit:
177173
if (usb_ep_queue(ep, req, GFP_ATOMIC))
178174
dev_err(uac->card->dev, "%d Error!\n", __LINE__);
179-
180-
if (update_alsa)
181-
snd_pcm_period_elapsed(substream);
182175
}
183176

184177
static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -241,35 +234,12 @@ static snd_pcm_uframes_t uac_pcm_pointer(struct snd_pcm_substream *substream)
241234
static int uac_pcm_hw_params(struct snd_pcm_substream *substream,
242235
struct snd_pcm_hw_params *hw_params)
243236
{
244-
struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
245-
struct uac_rtd_params *prm;
246-
int err;
247-
248-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
249-
prm = &uac->p_prm;
250-
else
251-
prm = &uac->c_prm;
252-
253-
err = snd_pcm_lib_malloc_pages(substream,
237+
return snd_pcm_lib_malloc_pages(substream,
254238
params_buffer_bytes(hw_params));
255-
if (err >= 0)
256-
prm->period_size = params_period_bytes(hw_params);
257-
258-
return err;
259239
}
260240

261241
static int uac_pcm_hw_free(struct snd_pcm_substream *substream)
262242
{
263-
struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
264-
struct uac_rtd_params *prm;
265-
266-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
267-
prm = &uac->p_prm;
268-
else
269-
prm = &uac->c_prm;
270-
271-
prm->period_size = 0;
272-
273243
return snd_pcm_lib_free_pages(substream);
274244
}
275245

0 commit comments

Comments
 (0)