[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251103052450.1028813-2-badhri@google.com>
Date: Mon, 3 Nov 2025 05:24:50 +0000
From: Badhri Jagan Sridharan <badhri@...gle.com>
To: heikki.krogerus@...ux.intel.com, gregkh@...uxfoundation.org,
badhri@...gle.com
Cc: amitsd@...gle.com, kyletso@...gle.com, rdbabiera@...gle.com,
linux-kernel@...r.kernel.org, linux-usb@...r.kernel.org
Subject: [PATCH v2 1/1] tcpm: Wraparound tcpm log and dont clear them when read
TCPM log do not wraparound by default and gets cleared when read.
This results in logs overflowing over time and the recent logs
containing relevant context to debug get dropped. Change this behavior
to wraparound the log by default and do not clear the log when dumped.
Adding the Kconfig option, TCPM_LOG_DISABLE_WRAPAROUND,
to disable wrap around and clear the log when read. Also adding a
a debugfs file node, tcpm_log_disable_wraparound, to switch between
the two during run time.
Signed-off-by: Badhri Jagan Sridharan <badhri@...gle.com>
Reviewed-by: Kyle Tso <kyletso@...gle.com>
Reviewed-by: Amit Sunil Dhamne <amitsd@...gle.com>
---
Changes since v1:
* Make wrapping around when full as the default behavior.
* Added a Kconfig and a debugfs node option to switch between the two
behaviors.
---
drivers/usb/typec/tcpm/Kconfig | 8 ++++++
drivers/usb/typec/tcpm/tcpm.c | 51 ++++++++++++++++++++++++++++++++--
2 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
index 8cdd84ca5d6f..4bb69f66c7bb 100644
--- a/drivers/usb/typec/tcpm/Kconfig
+++ b/drivers/usb/typec/tcpm/Kconfig
@@ -11,6 +11,14 @@ config TYPEC_TCPM
if TYPEC_TCPM
+config TCPM_LOG_DISABLE_WRAPAROUND
+ bool "Disable TCPM log wraparound"
+ depends on DEBUG_FS
+ help
+ When set, TCPM log do not wraparound and clears when dumped.
+ When not set(i.e. default), TCPM log wraps around when full and do
+ not clear when dumped.
+
config TYPEC_TCPCI
tristate "Type-C Port Controller Interface driver"
depends on I2C
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 4ca2746ce16b..2df21e5b5dff 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -591,6 +591,7 @@ struct tcpm_port {
int logbuffer_head;
int logbuffer_tail;
u8 *logbuffer[LOG_BUFFER_ENTRIES];
+ bool log_disable_wraparound;
#endif
};
@@ -723,7 +724,7 @@ static void _tcpm_log(struct tcpm_port *port, const char *fmt, va_list args)
vsnprintf(tmpbuffer, sizeof(tmpbuffer), fmt, args);
- if (tcpm_log_full(port)) {
+ if (port->log_disable_wraparound && tcpm_log_full(port)) {
port->logbuffer_head = max(port->logbuffer_head - 1, 0);
strcpy(tmpbuffer, "overflow");
}
@@ -748,6 +749,10 @@ static void _tcpm_log(struct tcpm_port *port, const char *fmt, va_list args)
tmpbuffer);
port->logbuffer_head = (port->logbuffer_head + 1) % LOG_BUFFER_ENTRIES;
+ if (!port->log_disable_wraparound && port->logbuffer_head ==
+ port->logbuffer_tail)
+ port->logbuffer_tail =
+ (port->logbuffer_tail + 1) % LOG_BUFFER_ENTRIES;
abort:
mutex_unlock(&port->logbuffer_lock);
}
@@ -863,7 +868,7 @@ static int tcpm_debug_show(struct seq_file *s, void *v)
seq_printf(s, "%s\n", port->logbuffer[tail]);
tail = (tail + 1) % LOG_BUFFER_ENTRIES;
}
- if (!seq_has_overflowed(s))
+ if (port->log_disable_wraparound && !seq_has_overflowed(s))
port->logbuffer_tail = tail;
mutex_unlock(&port->logbuffer_lock);
@@ -871,15 +876,57 @@ static int tcpm_debug_show(struct seq_file *s, void *v)
}
DEFINE_SHOW_ATTRIBUTE(tcpm_debug);
+static int tcpm_log_disable_wraparound_show(struct seq_file *s, void *v)
+{
+ struct tcpm_port *port = s->private;
+
+ mutex_lock(&port->logbuffer_lock);
+ seq_printf(s, "%d\n", port->log_disable_wraparound ? 1 : 0);
+ mutex_unlock(&port->logbuffer_lock);
+
+ return 0;
+}
+
+static ssize_t tcpm_log_disable_wraparound_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *seq_f = file->private_data;
+ bool log_disable_wraparound;
+ struct tcpm_port *port;
+ int err;
+
+ port = seq_f->private;
+ err = kstrtobool_from_user(user_buf, count, &log_disable_wraparound);
+ if (err)
+ return err;
+
+ mutex_lock(&port->logbuffer_lock);
+ if (port->log_disable_wraparound == log_disable_wraparound)
+ goto exit;
+
+ port->logbuffer_tail = port->logbuffer_head;
+ port->log_disable_wraparound = log_disable_wraparound;
+exit:
+ mutex_unlock(&port->logbuffer_lock);
+ return count;
+}
+
+DEFINE_SHOW_STORE_ATTRIBUTE(tcpm_log_disable_wraparound);
+
static void tcpm_debugfs_init(struct tcpm_port *port)
{
char name[NAME_MAX];
mutex_init(&port->logbuffer_lock);
+ port->log_disable_wraparound =
+ IS_ENABLED(CONFIG_TCPM_LOG_DISABLE_WRAPAROUND);
snprintf(name, NAME_MAX, "tcpm-%s", dev_name(port->dev));
port->dentry = debugfs_create_dir(name, usb_debug_root);
debugfs_create_file("log", S_IFREG | 0444, port->dentry, port,
&tcpm_debug_fops);
+ debugfs_create_file("tcpm_log_disable_wraparound", 0644, port->dentry,
+ port, &tcpm_log_disable_wraparound_fops);
}
static void tcpm_debugfs_exit(struct tcpm_port *port)
--
2.51.1.930.gacf6e81ea2-goog
Powered by blists - more mailing lists