Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save lategoodbye/74c25cd234694031362896115e3e4dfd to your computer and use it in GitHub Desktop.
Save lategoodbye/74c25cd234694031362896115e3e4dfd to your computer and use it in GitHub Desktop.
usb: dwc2: Add counter to debugfs
From cd7885dcfcae16cf8208cfe375c9901ba44586a5 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <[email protected]>
Date: Sun, 27 Apr 2025 11:22:01 +0200
Subject: [PATCH] usb: dwc2: Add counter to debugfs
Signed-off-by: Stefan Wahren <[email protected]>
---
drivers/usb/dwc2/core.h | 24 +++++++++++++++++++++
drivers/usb/dwc2/core_intr.c | 42 +++++++++++++++++++++++++++++-------
drivers/usb/dwc2/debugfs.c | 39 +++++++++++++++++++++++++++++++++
drivers/usb/dwc2/hcd_intr.c | 31 ++++++++++++++++++++------
4 files changed, 122 insertions(+), 14 deletions(-)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 34127b890b2a..d37166d30e32 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1105,6 +1105,30 @@ struct dwc2_hsotg {
struct debugfs_regset32 *regset;
bool needs_byte_swap;
+ u32 common_intr;
+ u32 gpwrdn_intr;
+ u32 mismatch_intr;
+ u32 otg_intr;
+ u32 conn_id_intr;
+ u32 disconnect_intr;
+ u32 session_req_intr;
+ u32 wakeup_intr;
+ u32 suspend_intr;
+ u32 lpm_intr;
+ u32 device_port_intr;
+ u32 host_port_intr;
+ u32 unhandled_intr;
+
+ u32 hcd_intr;
+ u32 hcd_unhandled_intr1;
+ u32 hcd_unhandled_intr2;
+ u32 hcd_sof_intr;
+ u32 hcd_rx_fifo_intr;
+ u32 hcd_tx_fifo_intr;
+ u32 hcd_port_intr;
+ u32 hcd_hc_intr;
+ u32 hcd_device_intr;
+
/* DWC OTG HW Release versions */
#define DWC2_CORE_REV_4_30a 0x4f54430a
#define DWC2_CORE_REV_2_71a 0x4f54271a
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 7d3e641806f8..42f7d3e11cd6 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -849,6 +849,8 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
spin_lock(&hsotg->lock);
+ hsotg->common_intr++;
+
if (!dwc2_is_controller_alive(hsotg)) {
dev_warn(hsotg->dev, "Controller is dead\n");
goto out;
@@ -869,26 +871,43 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
/* In case of hibernated state gintsts must not work */
if (hsotg->hibernated) {
dwc2_handle_gpwrdn_intr(hsotg);
+ hsotg->gpwrdn_intr++;
retval = IRQ_HANDLED;
goto out;
}
- if (gintsts & GINTSTS_MODEMIS)
+ if (gintsts & GINTSTS_MODEMIS) {
dwc2_handle_mode_mismatch_intr(hsotg);
- if (gintsts & GINTSTS_OTGINT)
+ hsotg->mismatch_intr++;
+ }
+ if (gintsts & GINTSTS_OTGINT) {
dwc2_handle_otg_intr(hsotg);
- if (gintsts & GINTSTS_CONIDSTSCHNG)
+ hsotg->otg_intr++;
+ }
+ if (gintsts & GINTSTS_CONIDSTSCHNG) {
dwc2_handle_conn_id_status_change_intr(hsotg);
- if (gintsts & GINTSTS_DISCONNINT)
+ hsotg->conn_id_intr++;
+ }
+ if (gintsts & GINTSTS_DISCONNINT) {
dwc2_handle_disconnect_intr(hsotg);
- if (gintsts & GINTSTS_SESSREQINT)
+ hsotg->disconnect_intr++;
+ }
+ if (gintsts & GINTSTS_SESSREQINT) {
dwc2_handle_session_req_intr(hsotg);
- if (gintsts & GINTSTS_WKUPINT)
+ hsotg->session_req_intr++;
+ }
+ if (gintsts & GINTSTS_WKUPINT) {
dwc2_handle_wakeup_detected_intr(hsotg);
- if (gintsts & GINTSTS_USBSUSP)
+ hsotg->wakeup_intr++;
+ }
+ if (gintsts & GINTSTS_USBSUSP) {
dwc2_handle_usb_suspend_intr(hsotg);
- if (gintsts & GINTSTS_LPMTRANRCVD)
+ hsotg->suspend_intr++;
+ }
+ if (gintsts & GINTSTS_LPMTRANRCVD) {
dwc2_handle_lpm_intr(hsotg);
+ hsotg->lpm_intr++;
+ }
if (gintsts & GINTSTS_PRTINT) {
/*
@@ -899,11 +918,18 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
dev_dbg(hsotg->dev,
" --Port interrupt received in Device mode--\n");
dwc2_handle_usb_port_intr(hsotg);
+ hsotg->device_port_intr++;
retval = IRQ_HANDLED;
+ } else {
+ if (retval == IRQ_NONE)
+ hsotg->host_port_intr++;
}
}
out:
+ if (retval == IRQ_NONE)
+ hsotg->unhandled_intr++;
+
spin_unlock(&hsotg->lock);
return retval;
}
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c
index 3116ac72747f..639aae73f359 100644
--- a/drivers/usb/dwc2/debugfs.c
+++ b/drivers/usb/dwc2/debugfs.c
@@ -772,6 +772,44 @@ static int dr_mode_show(struct seq_file *seq, void *v)
}
DEFINE_SHOW_ATTRIBUTE(dr_mode);
+#define print_stat(_seq, _ptr, _param) \
+seq_printf((_seq), "%-30s: %u\n", #_param, (_ptr)->_param)
+
+static int stats_show(struct seq_file *seq, void *v)
+{
+ struct dwc2_hsotg *hsotg = seq->private;
+
+ print_stat(seq, hsotg, common_intr);
+ print_stat(seq, hsotg, gpwrdn_intr);
+ print_stat(seq, hsotg, mismatch_intr);
+ print_stat(seq, hsotg, otg_intr);
+ print_stat(seq, hsotg, conn_id_intr);
+ print_stat(seq, hsotg, disconnect_intr);
+ print_stat(seq, hsotg, session_req_intr);
+ print_stat(seq, hsotg, wakeup_intr);
+ print_stat(seq, hsotg, suspend_intr);
+ print_stat(seq, hsotg, lpm_intr);
+ print_stat(seq, hsotg, device_port_intr);
+ print_stat(seq, hsotg, host_port_intr);
+ print_stat(seq, hsotg, unhandled_intr);
+
+ print_stat(seq, hsotg, hcd_intr);
+ print_stat(seq, hsotg, hcd_unhandled_intr1);
+ print_stat(seq, hsotg, hcd_unhandled_intr2);
+ print_stat(seq, hsotg, hcd_sof_intr);
+ print_stat(seq, hsotg, hcd_rx_fifo_intr);
+ print_stat(seq, hsotg, hcd_tx_fifo_intr);
+ print_stat(seq, hsotg, hcd_port_intr);
+ print_stat(seq, hsotg, hcd_hc_intr);
+ print_stat(seq, hsotg, hcd_device_intr);
+
+ print_stat(seq, hsotg, lx_state);
+ print_stat(seq, hsotg, op_state);
+ print_stat(seq, hsotg, bus_suspended);
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(stats);
+
int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
{
int ret;
@@ -783,6 +821,7 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
debugfs_create_file("params", 0444, root, hsotg, &params_fops);
debugfs_create_file("hw_params", 0444, root, hsotg, &hw_params_fops);
debugfs_create_file("dr_mode", 0444, root, hsotg, &dr_mode_fops);
+ debugfs_create_file("stats", 0444, root, hsotg, &stats_fops);
/* Add gadget debugfs nodes */
dwc2_hsotg_create_debug(hsotg);
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 5c7538d498dd..6ec4905d3ef8 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -2212,11 +2212,13 @@ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg)
}
spin_lock(&hsotg->lock);
+ hsotg->hcd_intr++;
/* Check if HOST Mode */
if (dwc2_is_host_mode(hsotg)) {
gintsts = dwc2_read_core_intr(hsotg);
if (!gintsts) {
+ hsotg->hcd_unhandled_intr1++;
spin_unlock(&hsotg->lock);
return retval;
}
@@ -2237,18 +2239,30 @@ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg)
"DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x\n",
gintsts);
- if (gintsts & GINTSTS_SOF)
+ if (gintsts & GINTSTS_SOF) {
dwc2_sof_intr(hsotg);
- if (gintsts & GINTSTS_RXFLVL)
+ hsotg->hcd_sof_intr++;
+ }
+ if (gintsts & GINTSTS_RXFLVL) {
dwc2_rx_fifo_level_intr(hsotg);
- if (gintsts & GINTSTS_NPTXFEMP)
+ hsotg->hcd_rx_fifo_intr++;
+ }
+ if (gintsts & GINTSTS_NPTXFEMP) {
dwc2_np_tx_fifo_empty_intr(hsotg);
- if (gintsts & GINTSTS_PRTINT)
+ hsotg->hcd_tx_fifo_intr++;
+ }
+ if (gintsts & GINTSTS_PRTINT) {
dwc2_port_intr(hsotg);
- if (gintsts & GINTSTS_HCHINT)
+ hsotg->hcd_port_intr++;
+ }
+ if (gintsts & GINTSTS_HCHINT) {
dwc2_hc_intr(hsotg);
- if (gintsts & GINTSTS_PTXFEMP)
+ hsotg->hcd_hc_intr++;
+ }
+ if (gintsts & GINTSTS_PTXFEMP) {
dwc2_perio_tx_fifo_empty_intr(hsotg);
+ hsotg->hcd_tx_fifo_intr++;
+ }
if (dbg_gintsts) {
dev_vdbg(hsotg->dev,
@@ -2258,6 +2272,11 @@ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg)
dwc2_readl(hsotg, GINTSTS),
dwc2_readl(hsotg, GINTMSK));
}
+
+ if (retval == IRQ_NONE)
+ hsotg->hcd_unhandled_intr2++;
+ } else {
+ hsotg->hcd_device_intr++;
}
spin_unlock(&hsotg->lock);
--
2.34.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment