forked from Minki/linux
usb: dwc3: workaround: missing disconnect event
DWC3 revisions <1.88a have an issue which would case a missing Disconnect event if cable is disconnected while there's a Setup packet pending the FIFO. Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
05870c5ba2
commit
df62df56e1
@ -578,6 +578,7 @@ struct dwc3_hwparams {
|
||||
* @ep0_bounced: true when we used bounce buffer
|
||||
* @ep0_expect_in: true when we expect a DATA IN transfer
|
||||
* @start_config_issued: true when StartConfig command has been issued
|
||||
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
|
||||
* @ep0_next_event: hold the next expected event
|
||||
* @ep0state: state of endpoint zero
|
||||
* @link_state: link state
|
||||
@ -633,6 +634,7 @@ struct dwc3 {
|
||||
unsigned ep0_bounced:1;
|
||||
unsigned ep0_expect_in:1;
|
||||
unsigned start_config_issued:1;
|
||||
unsigned setup_packet_pending:1;
|
||||
unsigned delayed_status:1;
|
||||
|
||||
enum dwc3_ep0_next ep0_next_event;
|
||||
|
@ -625,6 +625,7 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
|
||||
struct dwc3_ep *dep = dwc->eps[event->endpoint_number];
|
||||
|
||||
dep->flags &= ~DWC3_EP_BUSY;
|
||||
dwc->setup_packet_pending = false;
|
||||
|
||||
switch (dwc->ep0state) {
|
||||
case EP0_SETUP_PHASE:
|
||||
@ -726,6 +727,8 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum)
|
||||
static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
|
||||
const struct dwc3_event_depevt *event)
|
||||
{
|
||||
dwc->setup_packet_pending = true;
|
||||
|
||||
/*
|
||||
* This part is very tricky: If we has just handled
|
||||
* XferNotReady(Setup) and we're now expecting a
|
||||
|
@ -1640,6 +1640,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
|
||||
dwc->start_config_issued = false;
|
||||
|
||||
dwc->gadget.speed = USB_SPEED_UNKNOWN;
|
||||
dwc->setup_packet_pending = false;
|
||||
}
|
||||
|
||||
static void dwc3_gadget_usb3_phy_power(struct dwc3 *dwc, int on)
|
||||
@ -1676,6 +1677,37 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
|
||||
|
||||
dev_vdbg(dwc->dev, "%s\n", __func__);
|
||||
|
||||
/*
|
||||
* WORKAROUND: DWC3 revisions <1.88a have an issue which
|
||||
* would cause a missing Disconnect Event if there's a
|
||||
* pending Setup Packet in the FIFO.
|
||||
*
|
||||
* There's no suggested workaround on the official Bug
|
||||
* report, which states that "unless the driver/application
|
||||
* is doing any special handling of a disconnect event,
|
||||
* there is no functional issue".
|
||||
*
|
||||
* Unfortunately, it turns out that we _do_ some special
|
||||
* handling of a disconnect event, namely complete all
|
||||
* pending transfers, notify gadget driver of the
|
||||
* disconnection, and so on.
|
||||
*
|
||||
* Our suggested workaround is to follow the Disconnect
|
||||
* Event steps here, instead, based on a setup_packet_pending
|
||||
* flag. Such flag gets set whenever we have a XferNotReady
|
||||
* event on EP0 and gets cleared on XferComplete for the
|
||||
* same endpoint.
|
||||
*
|
||||
* Refers to:
|
||||
*
|
||||
* STAR#9000466709: RTL: Device : Disconnect event not
|
||||
* generated if setup packet pending in FIFO
|
||||
*/
|
||||
if (dwc->revision < DWC3_REVISION_188A) {
|
||||
if (dwc->setup_packet_pending)
|
||||
dwc3_gadget_disconnect_interrupt(dwc);
|
||||
}
|
||||
|
||||
/* Enable PHYs */
|
||||
dwc3_gadget_usb2_phy_power(dwc, true);
|
||||
dwc3_gadget_usb3_phy_power(dwc, true);
|
||||
|
Loading…
Reference in New Issue
Block a user