[PATCH 2/2] usb: dwc3: ep0: fix SetFeature(TEST)

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

 



From: Gerard Cauvy <g-cauvy1@xxxxxx>

When host requests us to enter a test mode,
we cannot directly enter the test mode before
Status Phase is completed, otherwise the core
will never be able to deliver the Status ZLP
to host, because it has already entered the
requested Test Mode.

In order to fix the error, we move the actual
start of Test Mode right after we receive
Transfer Complete event of the status phase.

Signed-off-by: Gerard Cauvy <g-cauvy1@xxxxxx>
Signed-off-by: Felipe Balbi <balbi@xxxxxx>
---
 drivers/usb/dwc3/core.h   |    3 +++
 drivers/usb/dwc3/ep0.c    |   20 ++++++++++++--------
 drivers/usb/dwc3/gadget.c |    1 +
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 71d958a..4dac982 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -684,6 +684,9 @@ struct dwc3 {
 
 	struct dwc3_hwparams	hwparams;
 	struct dentry		*root;
+
+	u8			test_mode;
+	u8			test_mode_nr;
 };
 
 /* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 5104dbf..e336f2a 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -316,7 +316,6 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 	u32			wValue;
 	u32			wIndex;
 	int			ret;
-	u32			mode;
 
 	wValue = le16_to_cpu(ctrl->wValue);
 	wIndex = le16_to_cpu(ctrl->wIndex);
@@ -355,13 +354,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 			if (!set)
 				return -EINVAL;
 
-			mode = wIndex >> 8;
-			ret = dwc3_gadget_set_test_mode(dwc, mode);
-			if (ret < 0) {
-				dev_dbg(dwc->dev, "Invalid Test #%d\n",
-						mode);
-				return ret;
-			}
+			dwc->test_mode_nr = wIndex >> 8;
+			dwc->test_mode = true;
 		}
 		break;
 
@@ -604,6 +598,15 @@ static void dwc3_ep0_complete_req(struct dwc3 *dwc,
 		dwc3_gadget_giveback(dep, r, 0);
 	}
 
+	if (dwc->test_mode) {
+		ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
+		if (ret < 0) {
+			dev_dbg(dwc->dev, "Invalid Test #%d\n",
+					dwc->test_mode_nr);
+			dwc3_ep0_stall_and_restart(dwc);
+		}
+	}
+
 	dwc->ep0state = EP0_SETUP_PHASE;
 	dwc3_ep0_out_start(dwc);
 }
@@ -611,6 +614,7 @@ static void dwc3_ep0_complete_req(struct dwc3 *dwc,
 static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
 			const struct dwc3_event_depevt *event)
 {
+	int			ret;
 	struct dwc3_ep		*dep = dwc->eps[event->endpoint_number];
 
 	dep->flags &= ~DWC3_EP_BUSY;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index c30ab6d..7632700 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1962,6 +1962,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg &= ~DWC3_DCTL_TSTCTRL_MASK;
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+	dwc->test_mode = false;
 
 	dwc3_stop_active_transfers(dwc);
 	dwc3_clear_stall_all_ep(dwc);
-- 
1.7.9

--
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