Skip to content

Commit f09ddcf

Browse files
Wesley Chenggregkh
authored andcommitted
usb: dwc3: gadget: Prevent EP queuing while stopping transfers
In the situations where the DWC3 gadget stops active transfers, once calling the dwc3_gadget_giveback(), there is a chance where a function driver can queue a new USB request in between the time where the dwc3 lock has been released and re-aquired. This occurs after we've already issued an ENDXFER command. When the stop active transfers continues to remove USB requests from all dep lists, the newly added request will also be removed, while controller still has an active TRB for it. This can lead to the controller accessing an unmapped memory address. Fix this by ensuring parameters to prevent EP queuing are set before calling the stop active transfers API. Fixes: ae7e861 ("usb: dwc3: Stop active transfers before halting the controller") Signed-off-by: Wesley Cheng <[email protected]> Link: https://lore.kernel.org/r/[email protected] Cc: stable <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 86629e0 commit f09ddcf

File tree

1 file changed

+5
-6
lines changed

1 file changed

+5
-6
lines changed

drivers/usb/dwc3/gadget.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -783,8 +783,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
783783

784784
trace_dwc3_gadget_ep_disable(dep);
785785

786-
dwc3_remove_requests(dwc, dep);
787-
788786
/* make sure HW endpoint isn't stalled */
789787
if (dep->flags & DWC3_EP_STALL)
790788
__dwc3_gadget_ep_set_halt(dep, 0, false);
@@ -803,6 +801,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
803801
dep->endpoint.desc = NULL;
804802
}
805803

804+
dwc3_remove_requests(dwc, dep);
805+
806806
return 0;
807807
}
808808

@@ -1617,7 +1617,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
16171617
{
16181618
struct dwc3 *dwc = dep->dwc;
16191619

1620-
if (!dep->endpoint.desc || !dwc->pullups_connected) {
1620+
if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
16211621
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
16221622
dep->name);
16231623
return -ESHUTDOWN;
@@ -2247,6 +2247,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
22472247
if (!is_on) {
22482248
u32 count;
22492249

2250+
dwc->connected = false;
22502251
/*
22512252
* In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
22522253
* Section 4.1.8 Table 4-7, it states that for a device-initiated
@@ -2271,7 +2272,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
22712272
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
22722273
dwc->ev_buf->length;
22732274
}
2274-
dwc->connected = false;
22752275
} else {
22762276
__dwc3_gadget_start(dwc);
22772277
}
@@ -3321,8 +3321,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
33213321
{
33223322
u32 reg;
33233323

3324-
dwc->connected = true;
3325-
33263324
/*
33273325
* WORKAROUND: DWC3 revisions <1.88a have an issue which
33283326
* would cause a missing Disconnect Event if there's a
@@ -3362,6 +3360,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
33623360
* transfers."
33633361
*/
33643362
dwc3_stop_active_transfers(dwc);
3363+
dwc->connected = true;
33653364

33663365
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
33673366
reg &= ~DWC3_DCTL_TSTCTRL_MASK;

0 commit comments

Comments
 (0)