Hi Guenter, On Fri, Apr 21, 2017 at 03:15:52PM -0700, Guenter Roeck wrote: > +/* > + * Logging > + */ > + > +#ifdef CONFIG_DEBUG_FS > + > +static bool tcpm_log_full(struct tcpm_port *port) > +{ > + return port->logbuffer_tail == > + (port->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; > +} > + > +static void _tcpm_log(struct tcpm_port *port, const char *fmt, va_list args) > +{ > + char tmpbuffer[LOG_BUFFER_ENTRY_SIZE]; > + u64 ts_nsec = local_clock(); > + unsigned long rem_nsec; > + > + if (!port->logbuffer[port->logbuffer_head]) { > + port->logbuffer[port->logbuffer_head] = > + kzalloc(LOG_BUFFER_ENTRY_SIZE, GFP_KERNEL); > + if (!port->logbuffer[port->logbuffer_head]) > + return; > + } > + > + vsnprintf(tmpbuffer, sizeof(tmpbuffer), fmt, args); > + > + mutex_lock(&port->logbuffer_lock); > + > + if (tcpm_log_full(port)) { > + port->logbuffer_head = max(port->logbuffer_head - 1, 0); > + strcpy(tmpbuffer, "overflow"); > + } > + > + if (port->logbuffer_head < 0 || > + port->logbuffer_head >= LOG_BUFFER_ENTRIES) { > + dev_warn(port->dev, > + "Bad log buffer index %d\n", port->logbuffer_head); > + goto abort; > + } > + > + if (!port->logbuffer[port->logbuffer_head]) { > + dev_warn(port->dev, > + "Log buffer index %d is NULL\n", port->logbuffer_head); > + goto abort; > + } > + > + rem_nsec = do_div(ts_nsec, 1000000000); > + scnprintf(port->logbuffer[port->logbuffer_head], > + LOG_BUFFER_ENTRY_SIZE, "[%5lu.%06lu] %s", > + (unsigned long)ts_nsec, rem_nsec / 1000, > + tmpbuffer); > + port->logbuffer_head = (port->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; > + > +abort: > + mutex_unlock(&port->logbuffer_lock); > +} > + > +static void tcpm_log(struct tcpm_port *port, const char *fmt, ...) > +{ > + va_list args; > + > + /* Do not log while disconnected and unattached */ > + if (tcpm_port_is_disconnected(port) && > + (port->state == SRC_UNATTACHED || port->state == SNK_UNATTACHED || > + port->state == DRP_TOGGLING)) > + return; > + > + va_start(args, fmt); > + _tcpm_log(port, fmt, args); > + va_end(args); > +} > + > +static void tcpm_log_force(struct tcpm_port *port, const char *fmt, ...) > +{ > + va_list args; > + > + va_start(args, fmt); > + _tcpm_log(port, fmt, args); > + va_end(args); > +} > + > +static int tcpm_seq_show(struct seq_file *s, void *v) > +{ > + struct tcpm_port *port = (struct tcpm_port *)s->private; > + int tail; > + > + mutex_lock(&port->logbuffer_lock); > + tail = port->logbuffer_tail; > + while (tail != port->logbuffer_head) { > + seq_printf(s, "%s\n", port->logbuffer[tail]); > + tail = (tail + 1) % LOG_BUFFER_ENTRIES; > + } > + if (!seq_has_overflowed(s)) > + port->logbuffer_tail = tail; > + mutex_unlock(&port->logbuffer_lock); > + > + return 0; > +} > + > +static int tcpm_debug_open(struct inode *inode, struct file *file) > +{ > + return single_open(file, tcpm_seq_show, inode->i_private); > +} > + > +static const struct file_operations tcpm_debug_operations = { > + .open = tcpm_debug_open, > + .llseek = seq_lseek, > + .read = seq_read, > + .release = single_release, > +}; > + > +static struct dentry *rootdir; > + > +static int tcpm_debugfs_init(struct tcpm_port *port) > +{ > + mutex_init(&port->logbuffer_lock); > + /* /sys/kernel/debug/tcpm/usbcX */ > + if (!rootdir) { > + rootdir = debugfs_create_dir("tcpm", NULL); > + if (!rootdir) > + return -ENOMEM; > + } > + > + port->dentry = debugfs_create_file(dev_name(port->dev), > + S_IFREG | 0444, rootdir, > + port, &tcpm_debug_operations); > + > + return 0; > +} > + > +static void tcpm_debugfs_exit(struct tcpm_port *port) > +{ > + debugfs_remove(port->dentry); > +} > + > +#else > > +static void tcpm_log(const struct tcpm_port *port, const char *fmt, ...) { } > +static int tcpm_debugfs_init(const struct tcpm_port *port) { return 0; } > +static void tcpm_debugfs_exit(const struct tcpm_port *port) { } > + > +#endif I think those should be converted into tracepoints at one point. Thanks, -- heikki -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html