From: Felipe Ferreri Tonello <eu@felipetonello.com>
To: linux-usb@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Felipe Balbi <balbi@kernel.org>,
"# v4 . 5+" <stable@vger.kernel.org>
Subject: Re: [PATCH] usb: gadget: f_midi: added spinlock on transmit function
Date: Wed, 9 Mar 2016 16:58:04 +0000 [thread overview]
Message-ID: <56E0561C.109@felipetonello.com> (raw)
In-Reply-To: <1457540261-32203-1-git-send-email-eu@felipetonello.com>
[-- Attachment #1: Type: text/plain, Size: 3675 bytes --]
Hi,
On 09/03/16 16:17, Felipe F. Tonello wrote:
> Since f_midi_transmit is called by both ALSA and USB sub-systems, it can
> potentially cause a race condition between both calls because f_midi_transmit
> is not reentrant nor thread-safe. This is due to an implementation detail that
> the transmit function looks for the next available usb request from the fifo
> and only enqueues it if there is data to send, otherwise just re-uses it. So,
> if both ALSA and USB frameworks calls this function at the same time,
> kfifo_seek() will return the same usb_request, which will cause a race
> condition.
>
> To solve this problem a syncronization mechanism is necessary. In this case it
> is used a spinlock since f_midi_transmit is also called by usb_request->complete
> callback in interrupt context.
>
> Cc: <stable@vger.kernel.org> # v4.5+
> Fixes: e1e3d7ec5da3 ("usb: gadget: f_midi: pre-allocate IN requests")
> Signed-off-by: Felipe F. Tonello <eu@felipetonello.com>
I'm sorry but I forgot to add v2 to the subject prefix.
Anyway, the changes from the previous patch is that this patch is on top
of Linus' v4.5-rc7 tag.
> ---
> drivers/usb/gadget/function/f_midi.c | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
> index fb1fe96d3215..ecb46d6abf0e 100644
> --- a/drivers/usb/gadget/function/f_midi.c
> +++ b/drivers/usb/gadget/function/f_midi.c
> @@ -24,6 +24,7 @@
> #include <linux/slab.h>
> #include <linux/device.h>
> #include <linux/kfifo.h>
> +#include <linux/spinlock.h>
>
> #include <sound/core.h>
> #include <sound/initval.h>
> @@ -92,6 +93,7 @@ struct f_midi {
> /* 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;
> + spinlock_t transmit_lock;
> };
>
> static inline struct f_midi *func_to_midi(struct usb_function *f)
> @@ -535,12 +537,15 @@ static void f_midi_drop_out_substreams(struct f_midi *midi)
> static void f_midi_transmit(struct f_midi *midi)
> {
> struct usb_ep *ep = midi->in_ep;
> + unsigned long flags;
> bool active;
>
> /* We only care about USB requests if IN endpoint is enabled */
> if (!ep || !ep->enabled)
> goto drop_out;
>
> + spin_lock_irqsave(&midi->transmit_lock, flags);
> +
> do {
> struct usb_request *req = NULL;
> unsigned int len, i;
> @@ -552,14 +557,17 @@ static void f_midi_transmit(struct f_midi *midi)
> len = kfifo_peek(&midi->in_req_fifo, &req);
> if (len != 1) {
> ERROR(midi, "%s: Couldn't get usb request\n", __func__);
> + spin_unlock_irqrestore(&midi->transmit_lock, flags);
> 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)
> + if (req->length > 0) {
> + spin_unlock_irqrestore(&midi->transmit_lock, flags);
> return;
> + }
>
> for (i = midi->in_last_port; i < MAX_PORTS; i++) {
> struct gmidi_in_port *port = midi->in_port[i];
> @@ -611,6 +619,8 @@ static void f_midi_transmit(struct f_midi *midi)
> }
> } while (active);
>
> + spin_unlock_irqrestore(&midi->transmit_lock, flags);
> +
> return;
>
> drop_out:
> @@ -1216,6 +1226,8 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
> if (status)
> goto setup_fail;
>
> + spin_lock_init(&midi->transmit_lock);
> +
> ++opts->refcnt;
> mutex_unlock(&opts->lock);
>
>
--
Felipe
[-- Attachment #2: 0x92698E6A.asc --]
[-- Type: application/pgp-keys, Size: 7195 bytes --]
next prev parent reply other threads:[~2016-03-09 16:56 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-09 16:17 [PATCH] usb: gadget: f_midi: added spinlock on transmit function Felipe F. Tonello
2016-03-09 16:58 ` Felipe Ferreri Tonello [this message]
-- strict thread matches above, loose matches on Subject: below --
2016-03-08 20:21 Felipe F. Tonello
2016-03-09 7:08 ` Felipe Balbi
2016-03-09 7:20 ` Felipe Balbi
2016-03-09 9:35 ` Felipe Ferreri Tonello
2016-03-09 10:33 ` Felipe Balbi
2016-03-09 16:15 ` Felipe Ferreri Tonello
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56E0561C.109@felipetonello.com \
--to=eu@felipetonello.com \
--cc=balbi@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.