[PATCH 2/3] USB: DWC3: Do not assign null values to some dep field until xfer is stopped

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux