Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756047AbbLHMyl (ORCPT ); Tue, 8 Dec 2015 07:54:41 -0500 Received: from mail-wm0-f48.google.com ([74.125.82.48]:33234 "EHLO mail-wm0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751839AbbLHMyk (ORCPT ); Tue, 8 Dec 2015 07:54:40 -0500 Subject: Re: [PATCH v6 3/3] usb: gadget: f_midi: pre-allocate IN requests To: linux-usb@vger.kernel.org References: <1448994662-21294-1-git-send-email-eu@felipetonello.com> <1448994662-21294-4-git-send-email-eu@felipetonello.com> Cc: linux-kernel@vger.kernel.org, Felipe Balbi , Clemens Ladisch , Greg Kroah-Hartman , Robert Baldyga From: Felipe Ferreri Tonello Message-ID: <5666D30D.8050703@felipetonello.com> Date: Tue, 8 Dec 2015 12:54:37 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.4.0 MIME-Version: 1.0 In-Reply-To: <1448994662-21294-4-git-send-email-eu@felipetonello.com> Content-Type: multipart/mixed; boundary="------------040605060305070105070404" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 17551 Lines: 444 This is a multi-part message in MIME format. --------------040605060305070105070404 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit On 01/12/15 18:31, Felipe F. Tonello wrote: > This patch introduces pre-allocation of IN endpoint USB requests. This > improves on latency (requires no usb request allocation on transmit) and avoid > several potential probles on allocating too many usb requests (which involves > DMA pool allocation problems). > > This implementation also handles better multiple MIDI Gadget ports, always > processing the last processed MIDI substream if the last USB request wasn't > enought to handle the whole stream. > > Signed-off-by: Felipe F. Tonello > --- > drivers/usb/gadget/function/f_midi.c | 166 +++++++++++++++++++++++++++-------- > drivers/usb/gadget/legacy/gmidi.c | 2 +- > 2 files changed, 129 insertions(+), 39 deletions(-) > > diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c > index 79dc611..fb1fe96d 100644 > --- a/drivers/usb/gadget/function/f_midi.c > +++ b/drivers/usb/gadget/function/f_midi.c > @@ -23,6 +23,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -88,6 +89,9 @@ struct f_midi { > int index; > char *id; > unsigned int buflen, qlen; > + /* This fifo is used as a buffer ring for pre-allocated IN usb_requests */ > + DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *); > + unsigned int in_last_port; > }; > > static inline struct f_midi *func_to_midi(struct usb_function *f) > @@ -95,7 +99,7 @@ static inline struct f_midi *func_to_midi(struct usb_function *f) > return container_of(f, struct f_midi, func); > } > > -static void f_midi_transmit(struct f_midi *midi, struct usb_request *req); > +static void f_midi_transmit(struct f_midi *midi); > > DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); > DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); > @@ -253,7 +257,8 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req) > } else if (ep == midi->in_ep) { > /* Our transmit completed. See if there's more to go. > * f_midi_transmit eats req, don't queue it again. */ > - f_midi_transmit(midi, req); > + req->length = 0; > + f_midi_transmit(midi); > return; > } > break; > @@ -264,10 +269,12 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req) > case -ESHUTDOWN: /* disconnect from host */ > VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status, > req->actual, req->length); > - if (ep == midi->out_ep) > + if (ep == midi->out_ep) { > f_midi_handle_out_data(ep, req); > - > - free_ep_req(ep, req); > + /* We don't need to free IN requests because it's handled > + * by the midi->in_req_fifo. */ > + free_ep_req(ep, req); > + } > return; > > case -EOVERFLOW: /* buffer overrun on read means that > @@ -334,6 +341,20 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) > if (err) > return err; > > + /* pre-allocate write usb requests to use on f_midi_transmit. */ > + while (kfifo_avail(&midi->in_req_fifo)) { > + struct usb_request *req = > + midi_alloc_ep_req(midi->in_ep, midi->buflen); > + > + if (req == NULL) > + return -ENOMEM; > + > + req->length = 0; > + req->complete = f_midi_complete; > + > + kfifo_put(&midi->in_req_fifo, req); > + } > + > /* allocate a bunch of read buffers and queue them all at once. */ > for (i = 0; i < midi->qlen && err == 0; i++) { > struct usb_request *req = > @@ -358,6 +379,7 @@ static void f_midi_disable(struct usb_function *f) > { > struct f_midi *midi = func_to_midi(f); > struct usb_composite_dev *cdev = f->config->cdev; > + struct usb_request *req = NULL; > > DBG(cdev, "disable\n"); > > @@ -367,6 +389,10 @@ static void f_midi_disable(struct usb_function *f) > */ > usb_ep_disable(midi->in_ep); > usb_ep_disable(midi->out_ep); > + > + /* release IN requests */ > + while (kfifo_get(&midi->in_req_fifo, &req)) > + free_ep_req(midi->in_ep, req); > } > > static int f_midi_snd_free(struct snd_device *device) > @@ -488,57 +514,113 @@ static void f_midi_transmit_byte(struct usb_request *req, > } > } > > -static void f_midi_transmit(struct f_midi *midi, struct usb_request *req) > +static void f_midi_drop_out_substreams(struct f_midi *midi) > { > - struct usb_ep *ep = midi->in_ep; > - int i; > - > - if (!ep) > - return; > - > - if (!req) > - req = midi_alloc_ep_req(ep, midi->buflen); > - > - if (!req) { > - ERROR(midi, "%s: alloc_ep_request failed\n", __func__); > - return; > - } > - req->length = 0; > - req->complete = f_midi_complete; > + unsigned int i; > > for (i = 0; i < MAX_PORTS; i++) { > struct gmidi_in_port *port = midi->in_port[i]; > struct snd_rawmidi_substream *substream = midi->in_substream[i]; > > - if (!port || !port->active || !substream) > + if (!port) > + break; > + > + if (!port->active || !substream) > continue; > > - while (req->length + 3 < midi->buflen) { > - uint8_t b; > - if (snd_rawmidi_transmit(substream, &b, 1) != 1) { > - port->active = 0; > + snd_rawmidi_drop_output(substream); > + } > +} > + > +static void f_midi_transmit(struct f_midi *midi) > +{ > + struct usb_ep *ep = midi->in_ep; > + bool active; > + > + /* We only care about USB requests if IN endpoint is enabled */ > + if (!ep || !ep->enabled) > + goto drop_out; > + > + do { > + struct usb_request *req = NULL; > + unsigned int len, i; > + > + active = false; > + > + /* We peek the request in order to reuse it if it fails > + * to enqueue on its endpoint */ > + len = kfifo_peek(&midi->in_req_fifo, &req); > + if (len != 1) { > + ERROR(midi, "%s: Couldn't get usb request\n", __func__); > + goto drop_out; > + } > + > + /* If buffer overrun, then we ignore this transmission. > + * IMPORTANT: This will cause the user-space rawmidi device to block until a) usb > + * requests have been completed or b) snd_rawmidi_write() times out. */ > + if (req->length > 0) > + return; > + > + for (i = midi->in_last_port; i < MAX_PORTS; i++) { > + struct gmidi_in_port *port = midi->in_port[i]; > + struct snd_rawmidi_substream *substream = midi->in_substream[i]; > + > + if (!port) { > + /* Reset counter when we reach the last available port */ > + midi->in_last_port = 0; > + break; > + } > + > + if (!port->active || !substream) > + continue; > + > + while (req->length + 3 < midi->buflen) { > + uint8_t b; > + > + if (snd_rawmidi_transmit(substream, &b, 1) != 1) { > + port->active = 0; > + break; > + } > + f_midi_transmit_byte(req, port, b); > + } > + > + active = !!port->active; > + /* Check if last port is still active, which means that > + * there is still data on that substream but this current > + * request run out of space. */ > + if (active) { > + midi->in_last_port = i; > + /* There is no need to re-iterate though midi ports. */ > break; > } > - f_midi_transmit_byte(req, port, b); > } > - } > > - if (req->length > 0 && ep->enabled) { > - int err; > + if (req->length > 0) { > + int err; > > - err = usb_ep_queue(ep, req, GFP_ATOMIC); > - if (err < 0) > - ERROR(midi, "%s queue req: %d\n", > - midi->in_ep->name, err); > - } else { > - free_ep_req(ep, req); > - } > + err = usb_ep_queue(ep, req, GFP_ATOMIC); > + if (err < 0) { > + ERROR(midi, "%s failed to queue req: %d\n", > + midi->in_ep->name, err); > + req->length = 0; /* Re-use request next time. */ > + } else { > + /* Upon success, put request at the back of the queue. */ > + kfifo_skip(&midi->in_req_fifo); > + kfifo_put(&midi->in_req_fifo, req); > + } > + } > + } while (active); > + > + return; > + > +drop_out: > + f_midi_drop_out_substreams(midi); > } > > static void f_midi_in_tasklet(unsigned long data) > { > struct f_midi *midi = (struct f_midi *) data; > - f_midi_transmit(midi, NULL); > + f_midi_transmit(midi); > } > > static int f_midi_in_open(struct snd_rawmidi_substream *substream) > @@ -664,6 +746,7 @@ static int f_midi_register_card(struct f_midi *midi) > goto fail; > } > midi->rmidi = rmidi; > + midi->in_last_port = 0; > strcpy(rmidi->name, card->shortname); > rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | > SNDRV_RAWMIDI_INFO_INPUT | > @@ -1053,6 +1136,7 @@ static void f_midi_free(struct usb_function *f) > mutex_lock(&opts->lock); > for (i = opts->in_ports - 1; i >= 0; --i) > kfree(midi->in_port[i]); > + kfifo_free(&midi->in_req_fifo); > kfree(midi); > --opts->refcnt; > mutex_unlock(&opts->lock); > @@ -1126,6 +1210,12 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) > midi->index = opts->index; > midi->buflen = opts->buflen; > midi->qlen = opts->qlen; > + midi->in_last_port = 0; > + > + status = kfifo_alloc(&midi->in_req_fifo, midi->qlen, GFP_KERNEL); > + if (status) > + goto setup_fail; > + > ++opts->refcnt; > mutex_unlock(&opts->lock); > > diff --git a/drivers/usb/gadget/legacy/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c > index be8e91d..f68c188 100644 > --- a/drivers/usb/gadget/legacy/gmidi.c > +++ b/drivers/usb/gadget/legacy/gmidi.c > @@ -53,7 +53,7 @@ MODULE_PARM_DESC(buflen, "MIDI buffer length"); > > static unsigned int qlen = 32; > module_param(qlen, uint, S_IRUGO); > -MODULE_PARM_DESC(qlen, "USB read request queue length"); > +MODULE_PARM_DESC(qlen, "USB read and write request queue length"); > > static unsigned int in_ports = 1; > module_param(in_ports, uint, S_IRUGO); > Just as a PS, I do have another patch refactoring the state machine on this driver, but it requires this change to be applied. So once it gets approved I will send the patch. Felipe --------------040605060305070105070404 Content-Type: application/pgp-keys; name="0x92698E6A.asc" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0x92698E6A.asc" -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2 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 SkAyCfQaSw== =JwBB -----END PGP PUBLIC KEY BLOCK----- --------------040605060305070105070404-- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/