^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2010 Google, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Erik Gilling <konkers@android.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2011-2013 NVIDIA Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "dev.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "channel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static DEFINE_MUTEX(debug_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned int host1x_debug_trace_cmdbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static pid_t host1x_debug_force_timeout_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static u32 host1x_debug_force_timeout_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static u32 host1x_debug_force_timeout_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) void host1x_debug_output(struct output *o, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) len = vsnprintf(o->buf, sizeof(o->buf), fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) o->fn(o->ctx, o->buf, len, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) void host1x_debug_cont(struct output *o, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) len = vsnprintf(o->buf, sizeof(o->buf), fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) o->fn(o->ctx, o->buf, len, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct host1x *m = dev_get_drvdata(ch->dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct output *o = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) mutex_lock(&ch->cdma.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) mutex_lock(&debug_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (show_fifo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) host1x_hw_show_channel_fifo(m, ch, o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) host1x_hw_show_channel_cdma(m, ch, o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) mutex_unlock(&debug_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) mutex_unlock(&ch->cdma.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void show_syncpts(struct host1x *m, struct output *o)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) host1x_debug_output(o, "---- syncpts ----\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) for (i = 0; i < host1x_syncpt_nb_pts(m); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u32 max = host1x_syncpt_read_max(m->syncpt + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 min = host1x_syncpt_load(m->syncpt + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (!min && !max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) host1x_debug_output(o, "id %u (%s) min %d max %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) i, m->syncpt[i].name, min, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) for (i = 0; i < host1x_syncpt_nb_bases(m); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u32 base_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) base_val = host1x_syncpt_load_wait_base(m->syncpt + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (base_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) host1x_debug_output(o, "waitbase id %u val %d\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) base_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) host1x_debug_output(o, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static void show_all(struct host1x *m, struct output *o, bool show_fifo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) host1x_hw_show_mlocks(m, o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) show_syncpts(m, o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) host1x_debug_output(o, "---- channels ----\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) for (i = 0; i < m->info->nb_channels; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct host1x_channel *ch = host1x_channel_get_index(m, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) show_channel(ch, o, show_fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) host1x_channel_put(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int host1x_debug_show_all(struct seq_file *s, void *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct output o = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .fn = write_to_seqfile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .ctx = s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) show_all(s->private, &o, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int host1x_debug_show(struct seq_file *s, void *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct output o = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .fn = write_to_seqfile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .ctx = s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) show_all(s->private, &o, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int host1x_debug_open_all(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return single_open(file, host1x_debug_show_all, inode->i_private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static const struct file_operations host1x_debug_all_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .open = host1x_debug_open_all,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static int host1x_debug_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return single_open(file, host1x_debug_show, inode->i_private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static const struct file_operations host1x_debug_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .open = host1x_debug_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static void host1x_debugfs_init(struct host1x *host1x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct dentry *de = debugfs_create_dir("tegra-host1x", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* Store the created entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) host1x->debugfs = de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) debugfs_create_file("status", S_IRUGO, de, host1x, &host1x_debug_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) debugfs_create_file("status_all", S_IRUGO, de, host1x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) &host1x_debug_all_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) debugfs_create_u32("trace_cmdbuf", S_IRUGO|S_IWUSR, de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) &host1x_debug_trace_cmdbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) host1x_hw_debug_init(host1x, de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) debugfs_create_u32("force_timeout_pid", S_IRUGO|S_IWUSR, de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) &host1x_debug_force_timeout_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) debugfs_create_u32("force_timeout_val", S_IRUGO|S_IWUSR, de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) &host1x_debug_force_timeout_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) debugfs_create_u32("force_timeout_channel", S_IRUGO|S_IWUSR, de,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) &host1x_debug_force_timeout_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void host1x_debugfs_exit(struct host1x *host1x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) debugfs_remove_recursive(host1x->debugfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) void host1x_debug_init(struct host1x *host1x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (IS_ENABLED(CONFIG_DEBUG_FS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) host1x_debugfs_init(host1x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) void host1x_debug_deinit(struct host1x *host1x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (IS_ENABLED(CONFIG_DEBUG_FS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) host1x_debugfs_exit(host1x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) void host1x_debug_dump(struct host1x *host1x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct output o = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .fn = write_to_printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) show_all(host1x, &o, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) void host1x_debug_dump_syncpts(struct host1x *host1x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct output o = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .fn = write_to_printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) show_syncpts(host1x, &o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }