From: Mathias Nyman Date: Wed, 3 Jun 2026 09:11:27 +0000 (+0300) Subject: xhci: dbc: add timestamps to DbC state changes in a new helper. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=724eab31dd7edea68b731b7635f91e3158c61d2a;p=thirdparty%2Fkernel%2Flinux.git xhci: dbc: add timestamps to DbC state changes in a new helper. The timestamp helps us track when a state changed the last time. It allows us to detect if DbC is stuck in connected state for too long, and can later be used to enable runtime suspend if there is no activity for some time Signed-off-by: Mathias Nyman Link: https://patch.msgid.link/20260603091132.1110849-11-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index 8cf0f0356bf1..34441ffa5e15 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -644,6 +644,12 @@ static int xhci_dbc_enable_dce(struct xhci_dbc *dbc, bool enable) done_state, 1000); } +static void xhci_dbc_set_state(struct xhci_dbc *dbc, enum dbc_state new_state) +{ + dbc->state_timestamp = jiffies; + dbc->state = new_state; +} + static int xhci_do_dbc_start(struct xhci_dbc *dbc) { int ret; @@ -663,7 +669,7 @@ static int xhci_do_dbc_start(struct xhci_dbc *dbc) if (ret) return ret; - dbc->state = DS_ENABLED; + xhci_dbc_set_state(dbc, DS_ENABLED); return 0; } @@ -725,7 +731,7 @@ static void xhci_dbc_stop(struct xhci_dbc *dbc) spin_lock_irqsave(&dbc->lock, flags); writel(0, &dbc->regs->control); - dbc->state = DS_DISABLED; + xhci_dbc_set_state(dbc, DS_DISABLED); spin_unlock_irqrestore(&dbc->lock, flags); xhci_dbc_mem_cleanup(dbc); @@ -896,7 +902,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) case DS_ENABLED: portsc = readl(&dbc->regs->portsc); if (portsc & DBC_PORTSC_CONN_STATUS) { - dbc->state = DS_CONNECTED; + xhci_dbc_set_state(dbc, DS_CONNECTED); dev_info(dbc->dev, "DbC connected\n"); } @@ -904,7 +910,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) case DS_CONNECTED: ctrl = readl(&dbc->regs->control); if (ctrl & DBC_CTRL_DBC_RUN) { - dbc->state = DS_CONFIGURED; + xhci_dbc_set_state(dbc, DS_CONFIGURED); dev_info(dbc->dev, "DbC configured\n"); portsc = readl(&dbc->regs->portsc); writel(portsc, &dbc->regs->portsc); @@ -919,7 +925,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) if (!(portsc & DBC_PORTSC_PORT_ENABLED) && !(portsc & DBC_PORTSC_CONN_STATUS)) { dev_info(dbc->dev, "DbC cable unplugged\n"); - dbc->state = DS_ENABLED; + xhci_dbc_set_state(dbc, DS_ENABLED); xhci_dbc_flush_requests(dbc); xhci_dbc_reinit_ep_rings(dbc); return EVT_DISC; @@ -929,7 +935,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) if (portsc & DBC_PORTSC_RESET_CHANGE) { dev_info(dbc->dev, "DbC port reset\n"); writel(portsc, &dbc->regs->portsc); - dbc->state = DS_ENABLED; + xhci_dbc_set_state(dbc, DS_ENABLED); xhci_dbc_flush_requests(dbc); xhci_dbc_reinit_ep_rings(dbc); return EVT_DISC; diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h index f4c0169a1b4d..b3efea43a6be 100644 --- a/drivers/usb/host/xhci-dbgcap.h +++ b/drivers/usb/host/xhci-dbgcap.h @@ -163,6 +163,7 @@ struct xhci_dbc { struct delayed_work event_work; unsigned int poll_interval; /* ms */ unsigned long xfer_timestamp; + unsigned long state_timestamp; unsigned resume_required:1; struct dbc_ep eps[2];