summaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/function
diff options
context:
space:
mode:
authorVladimir Zapolskiy <vladimir_zapolskiy@mentor.com>2018-06-21 17:22:50 +0200
committerFelipe Balbi <felipe.balbi@linux.intel.com>2018-07-17 10:12:51 +0300
commit773e53d50e227b0c03d0bb434c1636f6c49c75b2 (patch)
treef4658f651c458b9ffe03ebcbf2604f790d5d8b41 /drivers/usb/gadget/function
parent96afb54ece0ee903d23a7ac04ddc461413b972c4 (diff)
downloadlinux-773e53d50e227b0c03d0bb434c1636f6c49c75b2.tar.gz
linux-773e53d50e227b0c03d0bb434c1636f6c49c75b2.tar.bz2
linux-773e53d50e227b0c03d0bb434c1636f6c49c75b2.zip
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: 132fcb460839 ("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>
Diffstat (limited to 'drivers/usb/gadget/function')
-rw-r--r--drivers/usb/gadget/function/u_audio.c40
1 files changed, 5 insertions, 35 deletions
diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c
index b8fc2d6d156f..8a63009b7cd5 100644
--- a/drivers/usb/gadget/function/u_audio.c
+++ b/drivers/usb/gadget/function/u_audio.c
@@ -40,8 +40,6 @@ struct uac_rtd_params {
void *rbuf;
- size_t period_size;
-
unsigned max_psize; /* MaxPacketSize of endpoint */
struct uac_req *ureq;
@@ -83,7 +81,6 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
unsigned pending;
unsigned long flags;
unsigned int hw_ptr;
- bool update_alsa = false;
int status = req->status;
struct uac_req *ur = req->context;
struct snd_pcm_substream *substream;
@@ -136,11 +133,6 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
req->actual = req->length;
}
- pending = prm->hw_ptr % prm->period_size;
- pending += req->actual;
- if (pending >= prm->period_size)
- update_alsa = true;
-
hw_ptr = prm->hw_ptr;
spin_unlock_irqrestore(&prm->lock, flags);
@@ -171,14 +163,15 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
spin_lock_irqsave(&prm->lock, flags);
/* update hw_ptr after data is copied to memory */
prm->hw_ptr = (hw_ptr + req->actual) % runtime->dma_bytes;
+ hw_ptr = prm->hw_ptr;
spin_unlock_irqrestore(&prm->lock, flags);
+ if ((hw_ptr % snd_pcm_lib_period_bytes(substream)) < req->actual)
+ snd_pcm_period_elapsed(substream);
+
exit:
if (usb_ep_queue(ep, req, GFP_ATOMIC))
dev_err(uac->card->dev, "%d Error!\n", __LINE__);
-
- if (update_alsa)
- snd_pcm_period_elapsed(substream);
}
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)
static int uac_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
- struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
- struct uac_rtd_params *prm;
- int err;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac->p_prm;
- else
- prm = &uac->c_prm;
-
- err = snd_pcm_lib_malloc_pages(substream,
+ return snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
- if (err >= 0)
- prm->period_size = params_period_bytes(hw_params);
-
- return err;
}
static int uac_pcm_hw_free(struct snd_pcm_substream *substream)
{
- struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
- struct uac_rtd_params *prm;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac->p_prm;
- else
- prm = &uac->c_prm;
-
- prm->period_size = 0;
-
return snd_pcm_lib_free_pages(substream);
}