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.chen@xxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html