It is possible to receive xferinprogress when end transfer has been issued but its completion event has not been received. If we assign null values to some dep elements before end transfer event reception then software might abort. This patch prevents such scenarios. This situation can be reproduced when cable is physically disconnected after some isoc in transfer (testusb case 16). Signed-off-by: Pratyush Anand <pratyush.anand@xxxxxx> --- drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/gadget.c | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 5c6cd18..6cb45b1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -358,6 +358,7 @@ struct dwc3_event_buffer { * @direction: true for TX, false for RX * @stream_capable: true when streams are enabled * @end_xfer_issued: true when EndTransfer command has been issued + * @ep_disabled: true when endpoint is disabled */ struct dwc3_ep { struct usb_ep endpoint; @@ -396,6 +397,7 @@ struct dwc3_ep { unsigned direction:1; unsigned stream_capable:1; unsigned end_xfer_issued:1; + unsigned ep_disabled:1; }; enum dwc3_phy { diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fe2f4f9..61fe6e1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -505,6 +505,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg |= DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + dep->ep_disabled = false; if (!usb_endpoint_xfer_isoc(desc)) return 0; @@ -559,11 +560,15 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) reg &= ~DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); - dep->stream_capable = false; - dep->desc = NULL; - dep->comp_desc = NULL; - dep->type = 0; - dep->flags = 0; + if (!dep->end_xfer_issued) { + dep->stream_capable = false; + dep->desc = NULL; + dep->comp_desc = NULL; + dep->type = 0; + dep->flags = 0; + } + + dep->ep_disabled = true; return 0; } @@ -1764,6 +1769,13 @@ static void dwc3_ep_cmd_compl(struct dwc3_ep *dep, case DWC3_DEPCMD_ENDTRANSFER: dep->end_xfer_issued = false; dwc3_process_ep_cmd_complete(dep, event); + if (dep->ep_disabled) { + dep->stream_capable = false; + dep->desc = NULL; + dep->comp_desc = NULL; + dep->type = 0; + dep->flags = 0; + } break; case DWC3_DEPCMD_STARTTRANSFER: dep->res_trans_idx = param & 0x7f; -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html