mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
xhci: dbc: detect and recover hung DbC during enumeraton
Add a timeout between the detection of the debug host connection and the DbC Run transition to ‘1’. Toggle the DCE bit to re-enable DbC in order to retry the debug device enumeration process if the DbC run transition takes too long. Set the timeout to 2 seconds See xhci specification section 7.6.4.1 "Debug Capability Initialization" Also detect cable disconnect during enable and connected state. Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://patch.msgid.link/20260603091132.1110849-12-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
724eab31dd
commit
a3d34e5525
|
|
@ -901,23 +901,49 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc)
|
|||
return EVT_ERR;
|
||||
case DS_ENABLED:
|
||||
portsc = readl(&dbc->regs->portsc);
|
||||
ctrl = readl(&dbc->regs->control);
|
||||
|
||||
if (portsc & DBC_PORTSC_CONN_STATUS) {
|
||||
xhci_dbc_set_state(dbc, DS_CONNECTED);
|
||||
dev_info(dbc->dev, "DbC connected\n");
|
||||
} else if (!(ctrl & DBC_CTRL_DBC_ENABLE)) {
|
||||
dev_err(dbc->dev, "unexpected DbC disable, xHC reset?\n");
|
||||
}
|
||||
|
||||
return EVT_DONE;
|
||||
case DS_CONNECTED:
|
||||
ctrl = readl(&dbc->regs->control);
|
||||
portsc = readl(&dbc->regs->portsc);
|
||||
if (ctrl & DBC_CTRL_DBC_RUN) {
|
||||
xhci_dbc_set_state(dbc, DS_CONFIGURED);
|
||||
dev_info(dbc->dev, "DbC configured\n");
|
||||
portsc = readl(&dbc->regs->portsc);
|
||||
writel(portsc, &dbc->regs->portsc);
|
||||
ret = EVT_GSER;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Connection lost */
|
||||
if (!(portsc & DBC_PORTSC_CONN_STATUS)) {
|
||||
/* covers DCE == 0 as it also sets CONN_STATUS to 0 */
|
||||
dev_warn(dbc->dev, "DbC connection lost mid enumeration\n");
|
||||
xhci_dbc_set_state(dbc, DS_ENABLED);
|
||||
|
||||
return EVT_DONE;
|
||||
}
|
||||
|
||||
/* Enumeration timeout */
|
||||
if (time_is_before_jiffies(dbc->state_timestamp +
|
||||
msecs_to_jiffies(DBC_ENUMERATION_TIMEOUT))) {
|
||||
dev_err(dbc->dev, "DbC enumeration timeout, re-enabling DbC\n");
|
||||
dev_dbg(dbc->dev, "dcctrl %x, dcportsc %x\n", ctrl, portsc);
|
||||
|
||||
/* Toggle DCE to retry enumeration */
|
||||
ret = xhci_dbc_enable_dce(dbc, false);
|
||||
udelay(100);
|
||||
ret = xhci_dbc_enable_dce(dbc, true);
|
||||
xhci_dbc_set_state(dbc, DS_ENABLED);
|
||||
}
|
||||
|
||||
return EVT_DONE;
|
||||
case DS_CONFIGURED:
|
||||
/* Handle cable unplug event: */
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ struct dbc_ep {
|
|||
#define DBC_POLL_INTERVAL_DEFAULT 64 /* milliseconds */
|
||||
#define DBC_POLL_INTERVAL_MAX 5000 /* milliseconds */
|
||||
#define DBC_XFER_INACTIVITY_TIMEOUT 10 /* milliseconds */
|
||||
#define DBC_ENUMERATION_TIMEOUT 2000 /* milliseconds */
|
||||
/*
|
||||
* Private structure for DbC hardware state:
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user