diff options
author | Gerard Cauvy <g-cauvy1@ti.com> | 2012-02-10 05:21:18 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-02-10 06:11:46 -0500 |
commit | 3b637367ae40b6d3c20e30cb0cdd059e67bbf848 (patch) | |
tree | 0d74b50fafb3f1191a29b87a0dcd1660cb95d7d2 /drivers/usb/dwc3 | |
parent | 090725431b9636a0a59516ff0fe94933cf09a82b (diff) |
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.h | 3 | ||||
-rw-r--r-- | drivers/usb/dwc3/ep0.c | 21 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 1 |
3 files changed, 17 insertions, 8 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 71d958af2393..4dac9828577e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h | |||
@@ -684,6 +684,9 @@ struct dwc3 { | |||
684 | 684 | ||
685 | struct dwc3_hwparams hwparams; | 685 | struct dwc3_hwparams hwparams; |
686 | struct dentry *root; | 686 | struct dentry *root; |
687 | |||
688 | u8 test_mode; | ||
689 | u8 test_mode_nr; | ||
687 | }; | 690 | }; |
688 | 691 | ||
689 | /* -------------------------------------------------------------------------- */ | 692 | /* -------------------------------------------------------------------------- */ |
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 5104dbf46680..c20e30c8b695 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, | |||
316 | u32 wValue; | 316 | u32 wValue; |
317 | u32 wIndex; | 317 | u32 wIndex; |
318 | int ret; | 318 | int ret; |
319 | u32 mode; | ||
320 | 319 | ||
321 | wValue = le16_to_cpu(ctrl->wValue); | 320 | wValue = le16_to_cpu(ctrl->wValue); |
322 | wIndex = le16_to_cpu(ctrl->wIndex); | 321 | wIndex = le16_to_cpu(ctrl->wIndex); |
@@ -355,13 +354,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, | |||
355 | if (!set) | 354 | if (!set) |
356 | return -EINVAL; | 355 | return -EINVAL; |
357 | 356 | ||
358 | mode = wIndex >> 8; | 357 | dwc->test_mode_nr = wIndex >> 8; |
359 | ret = dwc3_gadget_set_test_mode(dwc, mode); | 358 | dwc->test_mode = true; |
360 | if (ret < 0) { | ||
361 | dev_dbg(dwc->dev, "Invalid Test #%d\n", | ||
362 | mode); | ||
363 | return ret; | ||
364 | } | ||
365 | } | 359 | } |
366 | break; | 360 | break; |
367 | 361 | ||
@@ -604,6 +598,17 @@ static void dwc3_ep0_complete_req(struct dwc3 *dwc, | |||
604 | dwc3_gadget_giveback(dep, r, 0); | 598 | dwc3_gadget_giveback(dep, r, 0); |
605 | } | 599 | } |
606 | 600 | ||
601 | if (dwc->test_mode) { | ||
602 | int ret; | ||
603 | |||
604 | ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr); | ||
605 | if (ret < 0) { | ||
606 | dev_dbg(dwc->dev, "Invalid Test #%d\n", | ||
607 | dwc->test_mode_nr); | ||
608 | dwc3_ep0_stall_and_restart(dwc); | ||
609 | } | ||
610 | } | ||
611 | |||
607 | dwc->ep0state = EP0_SETUP_PHASE; | 612 | dwc->ep0state = EP0_SETUP_PHASE; |
608 | dwc3_ep0_out_start(dwc); | 613 | dwc3_ep0_out_start(dwc); |
609 | } | 614 | } |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c30ab6da3d0e..76327005d54c 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) | |||
1962 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | 1962 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
1963 | reg &= ~DWC3_DCTL_TSTCTRL_MASK; | 1963 | reg &= ~DWC3_DCTL_TSTCTRL_MASK; |
1964 | dwc3_writel(dwc->regs, DWC3_DCTL, reg); | 1964 | dwc3_writel(dwc->regs, DWC3_DCTL, reg); |
1965 | dwc->test_mode = false; | ||
1965 | 1966 | ||
1966 | dwc3_stop_active_transfers(dwc); | 1967 | dwc3_stop_active_transfers(dwc); |
1967 | dwc3_clear_stall_all_ep(dwc); | 1968 | dwc3_clear_stall_all_ep(dwc); |