summaryrefslogtreecommitdiff
path: root/drivers/usb/cdns3/cdnsp-gadget.c
diff options
context:
space:
mode:
authorPawel Laszczak <pawell@cadence.com>2021-04-07 09:36:29 +0300
committerPeter Chen <peter.chen@kernel.org>2021-04-12 15:19:23 +0300
commit10076de33b5ed5b1e049593a611d2fd9eba60565 (patch)
tree7c2aa695c1a714f4a3b1ebd8a81d1c7a6232e396 /drivers/usb/cdns3/cdnsp-gadget.c
parent9ecc3eb03c37b54c507ba5127a4c781d36b0c121 (diff)
downloadlinux-10076de33b5ed5b1e049593a611d2fd9eba60565.tar.xz
usb: cdnsp: Fixes issue with Configure Endpoint command
Patch adds flag EP_UNCONFIGURED to detect whether endpoint was unconfigured. This flag is set in cdnsp_reset_device after Reset Device command. Among others this command disables all non control endpoints. Flag is used in cdnsp_gadget_ep_disable to protect controller against invoking Configure Endpoint command on disabled endpoint. Lack of this protection in some cases caused that Configure Endpoint command completed with Context State Error code completion. Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") Signed-off-by: Pawel Laszczak <pawell@cadence.com> Signed-off-by: Peter Chen <peter.chen@kernel.org>
Diffstat (limited to 'drivers/usb/cdns3/cdnsp-gadget.c')
-rw-r--r--drivers/usb/cdns3/cdnsp-gadget.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c
index d7d4bdd57f46..56707b6b0f57 100644
--- a/drivers/usb/cdns3/cdnsp-gadget.c
+++ b/drivers/usb/cdns3/cdnsp-gadget.c
@@ -727,7 +727,7 @@ int cdnsp_reset_device(struct cdnsp_device *pdev)
* are in Disabled state.
*/
for (i = 1; i < CDNSP_ENDPOINTS_NUM; ++i)
- pdev->eps[i].ep_state |= EP_STOPPED;
+ pdev->eps[i].ep_state |= EP_STOPPED | EP_UNCONFIGURED;
trace_cdnsp_handle_cmd_reset_dev(slot_ctx);
@@ -942,6 +942,7 @@ static int cdnsp_gadget_ep_enable(struct usb_ep *ep,
pep = to_cdnsp_ep(ep);
pdev = pep->pdev;
+ pep->ep_state &= ~EP_UNCONFIGURED;
if (dev_WARN_ONCE(pdev->dev, pep->ep_state & EP_ENABLED,
"%s is already enabled\n", pep->name))
@@ -1023,9 +1024,13 @@ static int cdnsp_gadget_ep_disable(struct usb_ep *ep)
goto finish;
}
- cdnsp_cmd_stop_ep(pdev, pep);
pep->ep_state |= EP_DIS_IN_RROGRESS;
- cdnsp_cmd_flush_ep(pdev, pep);
+
+ /* Endpoint was unconfigured by Reset Device command. */
+ if (!(pep->ep_state & EP_UNCONFIGURED)) {
+ cdnsp_cmd_stop_ep(pdev, pep);
+ cdnsp_cmd_flush_ep(pdev, pep);
+ }
/* Remove all queued USB requests. */
while (!list_empty(&pep->pending_list)) {
@@ -1043,10 +1048,12 @@ static int cdnsp_gadget_ep_disable(struct usb_ep *ep)
cdnsp_endpoint_zero(pdev, pep);
- ret = cdnsp_update_eps_configuration(pdev, pep);
+ if (!(pep->ep_state & EP_UNCONFIGURED))
+ ret = cdnsp_update_eps_configuration(pdev, pep);
+
cdnsp_free_endpoint_rings(pdev, pep);
- pep->ep_state &= ~EP_ENABLED;
+ pep->ep_state &= ~(EP_ENABLED | EP_UNCONFIGURED);
pep->ep_state |= EP_STOPPED;
finish: