[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <lsq.1510009382.516358685@decadent.org.uk>
Date: Mon, 06 Nov 2017 23:03:02 +0000
From: Ben Hutchings <ben@...adent.org.uk>
To: linux-kernel@...r.kernel.org, stable@...r.kernel.org
CC: akpm@...ux-foundation.org,
"Kuninori Morimoto" <kuninori.morimoto.gx@...esas.com>,
"Felipe Balbi" <balbi@...com>,
"Yoshihiro Shimoda" <yoshihiro.shimoda.uh@...esas.com>
Subject: [PATCH 3.16 028/294] usb: renesas_usbhs: gadget: fix re-enabling
pipe without re-connecting
3.16.50-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@...esas.com>
commit dfb87b8bfe09f933abaf387693992089f6f9053e upstream.
This patch fixes an issue that the renesas_usbhs driver in gadget mode
cannot work correctly even if I disabled DMAC of the driver when I used
the g_zero driver and the testusb tool.
When a usb cable is re-connected, the renesas_usbhs driver calls the
usbhsp_flags_init() (via usbhs_hotplug() --> usbhs_mod_call(start) -->
usbhsg_try_start() --> usbhs_pipe_init()). However, the driver doesn't
call the usbhsp_flags_init() when usbhsg_ep_disable() is called.
So, if a gadget driver calls usb_ep_enable() and usb_ep_disable() again
and again, the renesas_usbhs driver will output the following log:
renesas_usbhs renesas_usbhs: can't get pipe (BULK)
renesas_usbhs renesas_usbhs: wrong recip request
Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@...esas.com>
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@...esas.com>
Signed-off-by: Felipe Balbi <balbi@...com>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@...adent.org.uk>
---
drivers/usb/renesas_usbhs/mod_gadget.c | 2 ++
drivers/usb/renesas_usbhs/pipe.c | 10 ++++++++++
drivers/usb/renesas_usbhs/pipe.h | 1 +
3 files changed, 13 insertions(+)
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -607,11 +607,13 @@ usbhsg_ep_enable_end:
static int usbhsg_ep_disable(struct usb_ep *ep)
{
struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
+ struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
- if (!uep->pipe)
+ if (!pipe)
return -EINVAL;
usbhsg_pipe_disable(uep);
+ usbhs_pipe_free(pipe);
uep->pipe->mod_private = NULL;
uep->pipe = NULL;
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -640,6 +640,11 @@ static struct usbhs_pipe *usbhsp_get_pip
return pipe;
}
+static void usbhsp_put_pipe(struct usbhs_pipe *pipe)
+{
+ usbhsp_flags_init(pipe);
+}
+
void usbhs_pipe_init(struct usbhs_priv *priv,
int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
{
@@ -726,6 +731,11 @@ struct usbhs_pipe *usbhs_pipe_malloc(str
return pipe;
}
+void usbhs_pipe_free(struct usbhs_pipe *pipe)
+{
+ usbhsp_put_pipe(pipe);
+}
+
void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo)
{
if (pipe->fifo)
--- a/drivers/usb/renesas_usbhs/pipe.h
+++ b/drivers/usb/renesas_usbhs/pipe.h
@@ -75,6 +75,7 @@ struct usbhs_pipe_info {
char *usbhs_pipe_name(struct usbhs_pipe *pipe);
struct usbhs_pipe
*usbhs_pipe_malloc(struct usbhs_priv *priv, int endpoint_type, int dir_in);
+void usbhs_pipe_free(struct usbhs_pipe *pipe);
int usbhs_pipe_probe(struct usbhs_priv *priv);
void usbhs_pipe_remove(struct usbhs_priv *priv);
int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
Powered by blists - more mailing lists