From e636c8d336489bf3eed5878299e6cc045bbad077 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:17:29 +0000
Subject: [PATCH] debug lk
---
kernel/drivers/usb/dwc3/ep0.c | 174 ++++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 115 insertions(+), 59 deletions(-)
diff --git a/kernel/drivers/usb/dwc3/ep0.c b/kernel/drivers/usb/dwc3/ep0.c
index 154dadc..132c903 100644
--- a/kernel/drivers/usb/dwc3/ep0.c
+++ b/kernel/drivers/usb/dwc3/ep0.c
@@ -2,7 +2,7 @@
/*
* ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling
*
- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com
*
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
@@ -105,7 +105,7 @@
* IRQ we were waiting for is long gone.
*/
if (dep->flags & DWC3_EP_PENDING_REQUEST) {
- unsigned direction;
+ unsigned int direction;
direction = !!(dep->flags & DWC3_EP0_DIR_IN);
@@ -127,11 +127,11 @@
* handle it here.
*/
if (dwc->delayed_status) {
- unsigned direction;
+ unsigned int direction;
direction = !dwc->ep0_expect_in;
dwc->delayed_status = false;
- usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED);
+ usb_gadget_set_state(dwc->gadget, USB_STATE_CONFIGURED);
if (dwc->ep0state == EP0_STATUS_PHASE)
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
@@ -172,7 +172,7 @@
* XferNotReady(STATUS).
*/
if (dwc->three_stage_setup) {
- unsigned direction;
+ unsigned int direction;
direction = dwc->ep0_expect_in;
dwc->ep0state = EP0_DATA_PHASE;
@@ -197,7 +197,7 @@
int ret;
spin_lock_irqsave(&dwc->lock, flags);
- if (!dep->endpoint.desc) {
+ if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
dep->name);
ret = -ESHUTDOWN;
@@ -218,7 +218,7 @@
return ret;
}
-static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
+void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
@@ -239,6 +239,8 @@
dwc3_gadget_giveback(dep, req, -ECONNRESET);
}
+ dwc->eps[0]->trb_enqueue = 0;
+ dwc->eps[1]->trb_enqueue = 0;
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
}
@@ -271,6 +273,7 @@
{
struct dwc3_ep *dep;
int ret;
+ int i;
complete(&dwc->ep0_in_setup);
@@ -279,37 +282,50 @@
DWC3_TRBCTL_CONTROL_SETUP, false);
ret = dwc3_ep0_start_trans(dep);
WARN_ON(ret < 0);
+ for (i = 2; i < DWC3_ENDPOINTS_NUM; i++) {
+ struct dwc3_ep *dwc3_ep;
+
+ dwc3_ep = dwc->eps[i];
+ if (!dwc3_ep)
+ continue;
+
+ if (!(dwc3_ep->flags & DWC3_EP_DELAY_STOP))
+ continue;
+
+ dwc3_ep->flags &= ~DWC3_EP_DELAY_STOP;
+ if (dwc->connected)
+ dwc3_stop_active_transfer(dwc3_ep, true, true);
+ else
+ dwc3_remove_requests(dwc, dwc3_ep, -ESHUTDOWN);
+ }
}
static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le)
{
- struct dwc3_ep *dep = NULL;
+ struct dwc3_ep *dep;
u32 windex = le16_to_cpu(wIndex_le);
- u32 epnum, ep_index;
- u8 num, direction;
+ u32 ep, epnum;
+ u8 num_in_eps, num_out_eps, min_eps;
- epnum = windex & USB_ENDPOINT_NUMBER_MASK;
- direction = windex & USB_ENDPOINT_DIR_MASK;
- ep_index = 0;
+ num_in_eps = DWC3_NUM_IN_EPS(&dwc->hwparams);
+ num_out_eps = dwc->num_eps - num_in_eps;
+ min_eps = min_t(u8, num_in_eps, num_out_eps);
+ ep = windex & USB_ENDPOINT_NUMBER_MASK;
- for (num = 0; num < dwc->num_eps; num++) {
- dep = dwc->eps[num];
- if (!dep) {
- dev_warn(dwc->dev, "dep is NULL, num %d, windex 0x%08x\n",
- num, windex);
- return NULL;
- }
+ if (ep + 1 > min_eps && num_in_eps != num_out_eps) {
+ epnum = ep + min_eps;
- if ((direction == USB_DIR_IN && dep->direction) ||
- (direction == USB_DIR_OUT && !dep->direction))
- ep_index++;
-
- if (ep_index == epnum + 1)
- break;
+ } else {
+ epnum = ep << 1;
+ if ((windex & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+ epnum |= 1;
}
+ dep = dwc->eps[epnum];
+ if (dep == NULL)
+ return NULL;
- if (dep && (dep->flags & DWC3_EP_ENABLED))
+ if (dep->flags & DWC3_EP_ENABLED)
return dep;
return NULL;
@@ -342,7 +358,7 @@
/*
* LTM will be set once we know how to set this in HW.
*/
- usb_status |= dwc->gadget.is_selfpowered;
+ usb_status |= dwc->gadget->is_selfpowered;
if ((dwc->speed == DWC3_DSTS_SUPERSPEED) ||
(dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) {
@@ -396,9 +412,11 @@
if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
(dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS))
return -EINVAL;
+ if (set && dwc->dis_u1_entry_quirk)
+ return -EINVAL;
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- if (set && !dwc->dis_u1u2_quirk)
+ if (set)
reg |= DWC3_DCTL_INITU1ENA;
else
reg &= ~DWC3_DCTL_INITU1ENA;
@@ -418,9 +436,11 @@
if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
(dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS))
return -EINVAL;
+ if (set && dwc->dis_u2_entry_quirk)
+ return -EINVAL;
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- if (set && !dwc->dis_u1u2_quirk)
+ if (set)
reg |= DWC3_DCTL_INITU2ENA;
else
reg &= ~DWC3_DCTL_INITU2ENA;
@@ -438,11 +458,11 @@
return -EINVAL;
switch (wIndex >> 8) {
- case TEST_J:
- case TEST_K:
- case TEST_SE0_NAK:
- case TEST_PACKET:
- case TEST_FORCE_EN:
+ case USB_TEST_J:
+ case USB_TEST_K:
+ case USB_TEST_SE0_NAK:
+ case USB_TEST_PACKET:
+ case USB_TEST_FORCE_ENABLE:
dwc->test_mode_nr = wIndex >> 8;
dwc->test_mode = true;
break;
@@ -463,13 +483,13 @@
wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex);
- state = dwc->gadget.state;
+ state = dwc->gadget->state;
switch (wValue) {
case USB_DEVICE_REMOTE_WAKEUP:
break;
/*
- * 9.4.1 says only only for SS, in AddressState only for
+ * 9.4.1 says only for SS, in AddressState only for
* default control pipe
*/
case USB_DEVICE_U1_ENABLE:
@@ -537,6 +557,11 @@
ret = __dwc3_gadget_ep_set_halt(dep, set, true);
if (ret)
return -EINVAL;
+
+ /* ClearFeature(Halt) may need delayed status */
+ if (!set && (dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+ return USB_GADGET_DELAYED_STATUS;
+
break;
default:
return -EINVAL;
@@ -572,7 +597,7 @@
static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
- enum usb_device_state state = dwc->gadget.state;
+ enum usb_device_state state = dwc->gadget->state;
u32 addr;
u32 reg;
@@ -593,26 +618,28 @@
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
if (addr)
- usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
+ usb_gadget_set_state(dwc->gadget, USB_STATE_ADDRESS);
else
- usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
+ usb_gadget_set_state(dwc->gadget, USB_STATE_DEFAULT);
return 0;
}
static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
- int ret;
+ int ret = -EINVAL;
- spin_unlock(&dwc->lock);
- ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl);
- spin_lock(&dwc->lock);
+ if (dwc->async_callbacks) {
+ spin_unlock(&dwc->lock);
+ ret = dwc->gadget_driver->setup(dwc->gadget, ctrl);
+ spin_lock(&dwc->lock);
+ }
return ret;
}
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
- enum usb_device_state state = dwc->gadget.state;
+ enum usb_device_state state = dwc->gadget->state;
u32 cfg;
int ret;
u32 reg;
@@ -624,6 +651,8 @@
return -EINVAL;
case USB_STATE_ADDRESS:
+ dwc3_gadget_clear_tx_fifos(dwc);
+
ret = dwc3_ep0_delegate_req(dwc, ctrl);
/* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
@@ -635,7 +664,7 @@
* to change the state on the next usb_ep_queue()
*/
if (ret == 0)
- usb_gadget_set_state(&dwc->gadget,
+ usb_gadget_set_state(dwc->gadget,
USB_STATE_CONFIGURED);
/*
@@ -643,12 +672,10 @@
* nothing is pending from application.
*/
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- if (dwc->dis_u1u2_quirk)
- reg &= ~(DWC3_DCTL_ACCEPTU1ENA |
- DWC3_DCTL_ACCEPTU2ENA);
- else
- reg |= (DWC3_DCTL_ACCEPTU1ENA |
- DWC3_DCTL_ACCEPTU2ENA);
+ if (!dwc->dis_u1_entry_quirk)
+ reg |= DWC3_DCTL_ACCEPTU1ENA;
+ if (!dwc->dis_u2_entry_quirk)
+ reg |= DWC3_DCTL_ACCEPTU2ENA;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
}
break;
@@ -656,7 +683,7 @@
case USB_STATE_CONFIGURED:
ret = dwc3_ep0_delegate_req(dwc, ctrl);
if (!cfg && !ret)
- usb_gadget_set_state(&dwc->gadget,
+ usb_gadget_set_state(dwc->gadget,
USB_STATE_ADDRESS);
break;
default:
@@ -712,7 +739,7 @@
static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
struct dwc3_ep *dep;
- enum usb_device_state state = dwc->gadget.state;
+ enum usb_device_state state = dwc->gadget->state;
u16 wLength;
if (state == USB_STATE_DEFAULT)
@@ -756,7 +783,7 @@
if (wIndex || wLength)
return -EINVAL;
- dwc->gadget.isoch_delay = wValue;
+ dwc->gadget->isoch_delay = wValue;
return 0;
}
@@ -801,8 +828,9 @@
struct usb_ctrlrequest *ctrl = (void *) dwc->ep0_trb;
int ret = -EINVAL;
u32 len;
+ struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
- if (!dwc->gadget_driver)
+ if (!dwc->gadget_driver || !vdwc->softconnect || !dwc->connected)
goto out;
trace_dwc3_ctrl_req(ctrl);
@@ -1064,13 +1092,32 @@
__dwc3_ep0_do_control_status(dwc, dep);
}
-static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
+void dwc3_ep0_send_delayed_status(struct dwc3 *dwc)
+{
+ unsigned int direction = !dwc->ep0_expect_in;
+ struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
+
+ dwc->delayed_status = false;
+ vdwc->clear_stall_protocol = 0;
+
+ if (dwc->ep0state != EP0_STATUS_PHASE)
+ return;
+
+ __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
+}
+
+void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
{
struct dwc3_gadget_ep_cmd_params params;
u32 cmd;
int ret;
- if (!dep->resource_index)
+ /*
+ * For status/DATA OUT stage, TRB will be queued on ep0 out
+ * endpoint for which resource index is zero. Hence allow
+ * queuing ENDXFER command for ep0 out endpoint.
+ */
+ if (!dep->resource_index && dep->number)
return;
cmd = DWC3_DEPCMD_ENDTRANSFER;
@@ -1085,8 +1132,12 @@
static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
const struct dwc3_event_depevt *event)
{
+ struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
+
switch (event->status) {
case DEPEVT_STATUS_CONTROL_DATA:
+ if (!vdwc->softconnect || !dwc->connected)
+ return;
/*
* We already have a DATA transfer in the controller's cache,
* if we receive a XferNotReady(DATA) we will ignore it, unless
@@ -1111,6 +1162,11 @@
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
return;
+ if (dwc->setup_packet_pending) {
+ dwc3_ep0_stall_and_restart(dwc);
+ return;
+ }
+
dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status) {
@@ -1124,7 +1180,7 @@
*/
if (!list_empty(&dep->pending_list)) {
dwc->delayed_status = false;
- usb_gadget_set_state(&dwc->gadget,
+ usb_gadget_set_state(dwc->gadget,
USB_STATE_CONFIGURED);
dwc3_ep0_do_control_status(dwc, event);
}
--
Gitblit v1.6.2