]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xhci: dbc: add timestamps to DbC state changes in a new helper.
authorMathias Nyman <mathias.nyman@linux.intel.com>
Wed, 3 Jun 2026 09:11:27 +0000 (12:11 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Jun 2026 17:23:29 +0000 (19:23 +0200)
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 <mathias.nyman@linux.intel.com>
Link: https://patch.msgid.link/20260603091132.1110849-11-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-dbgcap.c
drivers/usb/host/xhci-dbgcap.h

index 8cf0f0356bf1c018925eb786d05fe22199b768ca..34441ffa5e157015546cac6b59a51587eb87973b 100644 (file)
@@ -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;
index f4c0169a1b4d1782897f63b8db12b95857e4bc12..b3efea43a6bee38a66f7cd79b6d5c8e68bf69ced 100644 (file)
@@ -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];