On Wed, Jan 04, 2017 at 10:19:23AM +0800, Peter Chen wrote:
> There are only two requests for uac2, it may not be enough at high
> loading system which usb interrupt handler can't be serviced on
> time, then the data will be lost since it is isoc transfer for audio.
> 
> In this patch, we introduce a parameter for the number for usb request,
> and the user can override it if current number for request is not enough
> for his/her use case.
> 
> Besides, update this parameter for legacy audio gadget and documentation.
> 
> Signed-off-by: Peter Chen <peter.c...@nxp.com>
> ---
>  Documentation/usb/gadget-testing.txt |  2 ++
>  drivers/usb/gadget/function/f_uac2.c | 39 
> +++++++++++++++++++++++++++---------
>  drivers/usb/gadget/function/u_uac2.h |  2 ++
>  drivers/usb/gadget/legacy/audio.c    |  1 +
>  4 files changed, 34 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/usb/gadget-testing.txt 
> b/Documentation/usb/gadget-testing.txt
> index 5819605..fb0cc4d 100644
> --- a/Documentation/usb/gadget-testing.txt
> +++ b/Documentation/usb/gadget-testing.txt
> @@ -632,6 +632,8 @@ The uac2 function provides these attributes in its 
> function directory:
>       p_chmask - playback channel mask
>       p_srate - playback sampling rate
>       p_ssize - playback sample size (bytes)
> +     req_number - the number of pre-allocated request for both capture
> +                  and playback
>  
>  The attributes have sane default values.
>  
> diff --git a/drivers/usb/gadget/function/f_uac2.c 
> b/drivers/usb/gadget/function/f_uac2.c
> index 3f4e478..f6a0d3a 100644
> --- a/drivers/usb/gadget/function/f_uac2.c
> +++ b/drivers/usb/gadget/function/f_uac2.c
> @@ -22,9 +22,6 @@
>  
>  #include "u_uac2.h"
>  
> -/* Keep everyone on toes */
> -#define USB_XFERS    2
> -
>  /*
>   * The driver implements a simple UAC_2 topology.
>   * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture
> @@ -78,7 +75,7 @@ struct uac2_rtd_params {
>       size_t period_size;
>  
>       unsigned max_psize;
> -     struct uac2_req ureq[USB_XFERS];
> +     struct uac2_req *ureq;
>  
>       spinlock_t lock;
>  };
> @@ -269,6 +266,8 @@ static int
>  uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
>  {
>       struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
> +     struct audio_dev *agdev = uac2_to_agdev(uac2);
> +     struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev);
>       struct uac2_rtd_params *prm;
>       unsigned long flags;
>       int err = 0;
> @@ -300,7 +299,7 @@ uac2_pcm_trigger(struct snd_pcm_substream *substream, int 
> cmd)
>  
>       /* Clear buffer after Play stops */
>       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
> -             memset(prm->rbuf, 0, prm->max_psize * USB_XFERS);
> +             memset(prm->rbuf, 0, prm->max_psize * uac2_opts->req_number);
>  
>       return err;
>  }
> @@ -943,6 +942,8 @@ static inline void
>  free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
>  {
>       struct snd_uac2_chip *uac2 = prm->uac2;
> +     struct audio_dev *agdev = uac2_to_agdev(uac2);
> +     struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev);
>       int i;
>  
>       if (!prm->ep_enabled)
> @@ -950,7 +951,7 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
>  
>       prm->ep_enabled = false;
>  
> -     for (i = 0; i < USB_XFERS; i++) {
> +     for (i = 0; i < uac2_opts->req_number; i++) {
>               if (prm->ureq[i].req) {
>                       usb_ep_dequeue(ep, prm->ureq[i].req);
>                       usb_ep_free_request(ep, prm->ureq[i].req);
> @@ -1095,7 +1096,13 @@ afunc_bind(struct usb_configuration *cfg, struct 
> usb_function *fn)
>  
>       prm = &agdev->uac2.c_prm;
>       prm->max_psize = hs_epout_desc.wMaxPacketSize;
> -     prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
> +     prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req),
> +                     GFP_KERNEL);
> +     if (!prm->ureq) {
> +             ret = -ENOMEM;
> +             goto err_free_descs;
> +     }
> +     prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL);
>       if (!prm->rbuf) {
>               prm->max_psize = 0;
>               ret = -ENOMEM;
> @@ -1104,7 +1111,13 @@ afunc_bind(struct usb_configuration *cfg, struct 
> usb_function *fn)
>  
>       prm = &agdev->uac2.p_prm;
>       prm->max_psize = hs_epin_desc.wMaxPacketSize;
> -     prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
> +     prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req),
> +                     GFP_KERNEL);
> +     if (!prm->ureq) {
> +             ret = -ENOMEM;
> +             goto err_free_descs;
> +     }
> +     prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL);
>       if (!prm->rbuf) {
>               prm->max_psize = 0;
>               ret = -ENOMEM;
> @@ -1117,6 +1130,8 @@ afunc_bind(struct usb_configuration *cfg, struct 
> usb_function *fn)
>       return 0;
>  
>  err_no_memory:
> +     kfree(agdev->uac2.p_prm.ureq);
> +     kfree(agdev->uac2.c_prm.ureq);
>       kfree(agdev->uac2.p_prm.rbuf);
>       kfree(agdev->uac2.c_prm.rbuf);
>  err_free_descs:
> @@ -1129,6 +1144,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, 
> unsigned alt)
>  {
>       struct usb_composite_dev *cdev = fn->config->cdev;
>       struct audio_dev *agdev = func_to_agdev(fn);
> +     struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev);
>       struct snd_uac2_chip *uac2 = &agdev->uac2;
>       struct usb_gadget *gadget = cdev->gadget;
>       struct device *dev = &uac2->pdev.dev;
> @@ -1159,7 +1175,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, 
> unsigned alt)
>               agdev->as_out_alt = alt;
>               req_len = prm->max_psize;
>       } else if (intf == agdev->as_in_intf) {
> -             struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev);
>               unsigned int factor, rate;
>               struct usb_endpoint_descriptor *ep_desc;
>  
> @@ -1205,7 +1220,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, 
> unsigned alt)
>       prm->ep_enabled = true;
>       usb_ep_enable(ep);
>  
> -     for (i = 0; i < USB_XFERS; i++) {
> +     for (i = 0; i < opts->req_number; i++) {
>               if (!prm->ureq[i].req) {
>                       req = usb_ep_alloc_request(ep, GFP_ATOMIC);
>                       if (req == NULL)
> @@ -1489,6 +1504,7 @@ UAC2_ATTRIBUTE(p_ssize);
>  UAC2_ATTRIBUTE(c_chmask);
>  UAC2_ATTRIBUTE(c_srate);
>  UAC2_ATTRIBUTE(c_ssize);
> +UAC2_ATTRIBUTE(req_number);
>  
>  static struct configfs_attribute *f_uac2_attrs[] = {
>       &f_uac2_opts_attr_p_chmask,
> @@ -1497,6 +1513,7 @@ static struct configfs_attribute *f_uac2_attrs[] = {
>       &f_uac2_opts_attr_c_chmask,
>       &f_uac2_opts_attr_c_srate,
>       &f_uac2_opts_attr_c_ssize,
> +     &f_uac2_opts_attr_req_number,
>       NULL,
>  };
>  
> @@ -1534,6 +1551,7 @@ static struct usb_function_instance 
> *afunc_alloc_inst(void)
>       opts->c_chmask = UAC2_DEF_CCHMASK;
>       opts->c_srate = UAC2_DEF_CSRATE;
>       opts->c_ssize = UAC2_DEF_CSSIZE;
> +     opts->req_number = UAC2_DEF_REQ_NUM;
>       return &opts->func_inst;
>  }
>  
> @@ -1562,6 +1580,7 @@ static void afunc_unbind(struct usb_configuration *c, 
> struct usb_function *f)
>  
>       prm = &agdev->uac2.c_prm;
>       kfree(prm->rbuf);
> +     kfree(prm->ureq);
>       usb_free_all_descriptors(f);
>  }
>  
> diff --git a/drivers/usb/gadget/function/u_uac2.h 
> b/drivers/usb/gadget/function/u_uac2.h
> index 78dd372..19eeb83 100644
> --- a/drivers/usb/gadget/function/u_uac2.h
> +++ b/drivers/usb/gadget/function/u_uac2.h
> @@ -24,6 +24,7 @@
>  #define UAC2_DEF_CCHMASK 0x3
>  #define UAC2_DEF_CSRATE 64000
>  #define UAC2_DEF_CSSIZE 2
> +#define UAC2_DEF_REQ_NUM 2
>  
>  struct f_uac2_opts {
>       struct usb_function_instance    func_inst;
> @@ -33,6 +34,7 @@ struct f_uac2_opts {
>       int                             c_chmask;
>       int                             c_srate;
>       int                             c_ssize;
> +     int                             req_number;
>       bool                            bound;
>  
>       struct mutex                    lock;
> diff --git a/drivers/usb/gadget/legacy/audio.c 
> b/drivers/usb/gadget/legacy/audio.c
> index 5d7b3c6..8a39f42 100644
> --- a/drivers/usb/gadget/legacy/audio.c
> +++ b/drivers/usb/gadget/legacy/audio.c
> @@ -229,6 +229,7 @@ static int audio_bind(struct usb_composite_dev *cdev)
>       uac2_opts->c_chmask = c_chmask;
>       uac2_opts->c_srate = c_srate;
>       uac2_opts->c_ssize = c_ssize;
> +     uac2_opts->req_number = UAC2_DEF_REQ_NUM;
>  #else
>       uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst);
>       uac1_opts->fn_play = fn_play;
> -- 

A nice ping...

-- 

Best Regards,
Peter Chen
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to