Skip to content

Commit 9b989b4

Browse files
shimodaygregkh
authored andcommitted
usb: renesas_usbhs: gadget: disable all eps when the driver stops
commit b8b9c97 upstream. A gadget driver will not disable eps immediately when ->disconnect() is called. But, since this driver assumes all eps stop after the ->disconnect(), unexpected behavior happens (especially in system suspend). So, this patch disables all eps in usbhsg_try_stop(). After disabling eps by renesas_usbhs driver, since some functions will be called by both a gadget and renesas_usbhs driver, renesas_usbhs driver should protect uep->pipe. To protect uep->pipe easily, this patch adds a new lock in struct usbhsg_uep. Fixes: 2f98382 ("usb: renesas_usbhs: Add Renesas USBHS Gadget") Signed-off-by: Yoshihiro Shimoda <[email protected]> Signed-off-by: Felipe Balbi <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent abe87c1 commit 9b989b4

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

drivers/usb/renesas_usbhs/mod_gadget.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct usbhsg_gpriv;
3737
struct usbhsg_uep {
3838
struct usb_ep ep;
3939
struct usbhs_pipe *pipe;
40+
spinlock_t lock; /* protect the pipe */
4041

4142
char ep_name[EP_NAME_SIZE];
4243

@@ -638,17 +639,26 @@ static int usbhsg_ep_enable(struct usb_ep *ep,
638639
static int usbhsg_ep_disable(struct usb_ep *ep)
639640
{
640641
struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
641-
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
642+
struct usbhs_pipe *pipe;
643+
unsigned long flags;
644+
int ret = 0;
642645

643-
if (!pipe)
644-
return -EINVAL;
646+
spin_lock_irqsave(&uep->lock, flags);
647+
pipe = usbhsg_uep_to_pipe(uep);
648+
if (!pipe) {
649+
ret = -EINVAL;
650+
goto out;
651+
}
645652

646653
usbhsg_pipe_disable(uep);
647654
usbhs_pipe_free(pipe);
648655

649656
uep->pipe->mod_private = NULL;
650657
uep->pipe = NULL;
651658

659+
out:
660+
spin_unlock_irqrestore(&uep->lock, flags);
661+
652662
return 0;
653663
}
654664

@@ -698,8 +708,11 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
698708
{
699709
struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
700710
struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
701-
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
711+
struct usbhs_pipe *pipe;
712+
unsigned long flags;
702713

714+
spin_lock_irqsave(&uep->lock, flags);
715+
pipe = usbhsg_uep_to_pipe(uep);
703716
if (pipe)
704717
usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
705718

@@ -708,6 +721,7 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
708721
* even if the pipe is NULL.
709722
*/
710723
usbhsg_queue_pop(uep, ureq, -ECONNRESET);
724+
spin_unlock_irqrestore(&uep->lock, flags);
711725

712726
return 0;
713727
}
@@ -854,10 +868,10 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
854868
{
855869
struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
856870
struct usbhs_mod *mod = usbhs_mod_get_current(priv);
857-
struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
871+
struct usbhsg_uep *uep;
858872
struct device *dev = usbhs_priv_to_dev(priv);
859873
unsigned long flags;
860-
int ret = 0;
874+
int ret = 0, i;
861875

862876
/******************** spin lock ********************/
863877
usbhs_lock(priv, flags);
@@ -889,7 +903,9 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
889903
usbhs_sys_set_test_mode(priv, 0);
890904
usbhs_sys_function_ctrl(priv, 0);
891905

892-
usbhsg_ep_disable(&dcp->ep);
906+
/* disable all eps */
907+
usbhsg_for_each_uep_with_dcp(uep, gpriv, i)
908+
usbhsg_ep_disable(&uep->ep);
893909

894910
dev_dbg(dev, "stop gadget\n");
895911

@@ -1072,6 +1088,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
10721088
ret = -ENOMEM;
10731089
goto usbhs_mod_gadget_probe_err_gpriv;
10741090
}
1091+
spin_lock_init(&uep->lock);
10751092

10761093
gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
10771094
dev_info(dev, "%stransceiver found\n",

0 commit comments

Comments
 (0)