summaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorGerard Cauvy <g-cauvy1@ti.com>2012-02-10 12:21:18 +0200
committerFelipe Balbi <balbi@ti.com>2012-02-10 13:11:46 +0200
commit3b637367ae40b6d3c20e30cb0cdd059e67bbf848 (patch)
tree0d74b50fafb3f1191a29b87a0dcd1660cb95d7d2 /drivers/usb/dwc3
parent090725431b9636a0a59516ff0fe94933cf09a82b (diff)
downloadop-kernel-dev-3b637367ae40b6d3c20e30cb0cdd059e67bbf848.zip
op-kernel-dev-3b637367ae40b6d3c20e30cb0cdd059e67bbf848.tar.gz
usb: dwc3: ep0: fix SetFeature(TEST)
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@ti.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/core.h3
-rw-r--r--drivers/usb/dwc3/ep0.c21
-rw-r--r--drivers/usb/dwc3/gadget.c1
3 files changed, 17 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..c20e30c 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,17 @@ static void dwc3_ep0_complete_req(struct dwc3 *dwc,
dwc3_gadget_giveback(dep, r, 0);
}
+ if (dwc->test_mode) {
+ int ret;
+
+ 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);
}
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);
OpenPOWER on IntegriCloud