Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: uac2: add req_number as parameter

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@nxp.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>

authored by

Peter Chen and committed by
Felipe Balbi
e92b9d44 ec33efe2

+34 -10
+2
Documentation/usb/gadget-testing.txt
··· 632 632 p_chmask - playback channel mask 633 633 p_srate - playback sampling rate 634 634 p_ssize - playback sample size (bytes) 635 + req_number - the number of pre-allocated request for both capture 636 + and playback 635 637 636 638 The attributes have sane default values. 637 639
+29 -10
drivers/usb/gadget/function/f_uac2.c
··· 22 22 23 23 #include "u_uac2.h" 24 24 25 - /* Keep everyone on toes */ 26 - #define USB_XFERS 2 27 - 28 25 /* 29 26 * The driver implements a simple UAC_2 topology. 30 27 * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture ··· 75 78 size_t period_size; 76 79 77 80 unsigned max_psize; 78 - struct uac2_req ureq[USB_XFERS]; 81 + struct uac2_req *ureq; 79 82 80 83 spinlock_t lock; 81 84 }; ··· 266 269 uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 267 270 { 268 271 struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); 272 + struct audio_dev *agdev = uac2_to_agdev(uac2); 273 + struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev); 269 274 struct uac2_rtd_params *prm; 270 275 unsigned long flags; 271 276 int err = 0; ··· 299 300 300 301 /* Clear buffer after Play stops */ 301 302 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss) 302 - memset(prm->rbuf, 0, prm->max_psize * USB_XFERS); 303 + memset(prm->rbuf, 0, prm->max_psize * uac2_opts->req_number); 303 304 304 305 return err; 305 306 } ··· 942 943 free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) 943 944 { 944 945 struct snd_uac2_chip *uac2 = prm->uac2; 946 + struct audio_dev *agdev = uac2_to_agdev(uac2); 947 + struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev); 945 948 int i; 946 949 947 950 if (!prm->ep_enabled) ··· 951 950 952 951 prm->ep_enabled = false; 953 952 954 - for (i = 0; i < USB_XFERS; i++) { 953 + for (i = 0; i < uac2_opts->req_number; i++) { 955 954 if (prm->ureq[i].req) { 956 955 usb_ep_dequeue(ep, prm->ureq[i].req); 957 956 usb_ep_free_request(ep, prm->ureq[i].req); ··· 1096 1095 1097 1096 prm = &agdev->uac2.c_prm; 1098 1097 prm->max_psize = hs_epout_desc.wMaxPacketSize; 1099 - prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); 1098 + prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req), 1099 + GFP_KERNEL); 1100 + if (!prm->ureq) { 1101 + ret = -ENOMEM; 1102 + goto err_free_descs; 1103 + } 1104 + prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL); 1100 1105 if (!prm->rbuf) { 1101 1106 prm->max_psize = 0; 1102 1107 ret = -ENOMEM; ··· 1111 1104 1112 1105 prm = &agdev->uac2.p_prm; 1113 1106 prm->max_psize = hs_epin_desc.wMaxPacketSize; 1114 - prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); 1107 + prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req), 1108 + GFP_KERNEL); 1109 + if (!prm->ureq) { 1110 + ret = -ENOMEM; 1111 + goto err_free_descs; 1112 + } 1113 + prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL); 1115 1114 if (!prm->rbuf) { 1116 1115 prm->max_psize = 0; 1117 1116 ret = -ENOMEM; ··· 1130 1117 return 0; 1131 1118 1132 1119 err_no_memory: 1120 + kfree(agdev->uac2.p_prm.ureq); 1121 + kfree(agdev->uac2.c_prm.ureq); 1133 1122 kfree(agdev->uac2.p_prm.rbuf); 1134 1123 kfree(agdev->uac2.c_prm.rbuf); 1135 1124 err_free_descs: ··· 1144 1129 { 1145 1130 struct usb_composite_dev *cdev = fn->config->cdev; 1146 1131 struct audio_dev *agdev = func_to_agdev(fn); 1132 + struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev); 1147 1133 struct snd_uac2_chip *uac2 = &agdev->uac2; 1148 1134 struct usb_gadget *gadget = cdev->gadget; 1149 1135 struct device *dev = &uac2->pdev.dev; ··· 1175 1159 agdev->as_out_alt = alt; 1176 1160 req_len = prm->max_psize; 1177 1161 } else if (intf == agdev->as_in_intf) { 1178 - struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev); 1179 1162 unsigned int factor, rate; 1180 1163 struct usb_endpoint_descriptor *ep_desc; 1181 1164 ··· 1220 1205 prm->ep_enabled = true; 1221 1206 usb_ep_enable(ep); 1222 1207 1223 - for (i = 0; i < USB_XFERS; i++) { 1208 + for (i = 0; i < opts->req_number; i++) { 1224 1209 if (!prm->ureq[i].req) { 1225 1210 req = usb_ep_alloc_request(ep, GFP_ATOMIC); 1226 1211 if (req == NULL) ··· 1504 1489 UAC2_ATTRIBUTE(c_chmask); 1505 1490 UAC2_ATTRIBUTE(c_srate); 1506 1491 UAC2_ATTRIBUTE(c_ssize); 1492 + UAC2_ATTRIBUTE(req_number); 1507 1493 1508 1494 static struct configfs_attribute *f_uac2_attrs[] = { 1509 1495 &f_uac2_opts_attr_p_chmask, ··· 1513 1497 &f_uac2_opts_attr_c_chmask, 1514 1498 &f_uac2_opts_attr_c_srate, 1515 1499 &f_uac2_opts_attr_c_ssize, 1500 + &f_uac2_opts_attr_req_number, 1516 1501 NULL, 1517 1502 }; 1518 1503 ··· 1551 1534 opts->c_chmask = UAC2_DEF_CCHMASK; 1552 1535 opts->c_srate = UAC2_DEF_CSRATE; 1553 1536 opts->c_ssize = UAC2_DEF_CSSIZE; 1537 + opts->req_number = UAC2_DEF_REQ_NUM; 1554 1538 return &opts->func_inst; 1555 1539 } 1556 1540 ··· 1580 1562 1581 1563 prm = &agdev->uac2.c_prm; 1582 1564 kfree(prm->rbuf); 1565 + kfree(prm->ureq); 1583 1566 usb_free_all_descriptors(f); 1584 1567 } 1585 1568
+2
drivers/usb/gadget/function/u_uac2.h
··· 24 24 #define UAC2_DEF_CCHMASK 0x3 25 25 #define UAC2_DEF_CSRATE 64000 26 26 #define UAC2_DEF_CSSIZE 2 27 + #define UAC2_DEF_REQ_NUM 2 27 28 28 29 struct f_uac2_opts { 29 30 struct usb_function_instance func_inst; ··· 34 33 int c_chmask; 35 34 int c_srate; 36 35 int c_ssize; 36 + int req_number; 37 37 bool bound; 38 38 39 39 struct mutex lock;
+1
drivers/usb/gadget/legacy/audio.c
··· 229 229 uac2_opts->c_chmask = c_chmask; 230 230 uac2_opts->c_srate = c_srate; 231 231 uac2_opts->c_ssize = c_ssize; 232 + uac2_opts->req_number = UAC2_DEF_REQ_NUM; 232 233 #else 233 234 uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst); 234 235 uac1_opts->fn_play = fn_play;