1 // SPDX-License-Identifier: GPL-2.0-only
3 * Sync File validation framework and debug information
5 * Copyright (C) 2012 Google, Inc.
8 #include <linux/debugfs.h>
9 #include "sync_debug.h"
11 static struct dentry
*dbgfs
;
13 static LIST_HEAD(sync_timeline_list_head
);
14 static DEFINE_SPINLOCK(sync_timeline_list_lock
);
15 static LIST_HEAD(sync_file_list_head
);
16 static DEFINE_SPINLOCK(sync_file_list_lock
);
18 void sync_timeline_debug_add(struct sync_timeline
*obj
)
22 spin_lock_irqsave(&sync_timeline_list_lock
, flags
);
23 list_add_tail(&obj
->sync_timeline_list
, &sync_timeline_list_head
);
24 spin_unlock_irqrestore(&sync_timeline_list_lock
, flags
);
27 void sync_timeline_debug_remove(struct sync_timeline
*obj
)
31 spin_lock_irqsave(&sync_timeline_list_lock
, flags
);
32 list_del(&obj
->sync_timeline_list
);
33 spin_unlock_irqrestore(&sync_timeline_list_lock
, flags
);
36 void sync_file_debug_add(struct sync_file
*sync_file
)
40 spin_lock_irqsave(&sync_file_list_lock
, flags
);
41 list_add_tail(&sync_file
->sync_file_list
, &sync_file_list_head
);
42 spin_unlock_irqrestore(&sync_file_list_lock
, flags
);
45 void sync_file_debug_remove(struct sync_file
*sync_file
)
49 spin_lock_irqsave(&sync_file_list_lock
, flags
);
50 list_del(&sync_file
->sync_file_list
);
51 spin_unlock_irqrestore(&sync_file_list_lock
, flags
);
54 static const char *sync_status_str(int status
)
65 static void sync_print_fence(struct seq_file
*s
,
66 struct dma_fence
*fence
, bool show
)
68 struct sync_timeline
*parent
= dma_fence_parent(fence
);
71 status
= dma_fence_get_status_locked(fence
);
73 seq_printf(s
, " %s%sfence %s",
74 show
? parent
->name
: "",
76 sync_status_str(status
));
78 if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT
, &fence
->flags
)) {
79 struct timespec64 ts64
=
80 ktime_to_timespec64(fence
->timestamp
);
82 seq_printf(s
, "@%lld.%09ld", (s64
)ts64
.tv_sec
, ts64
.tv_nsec
);
85 if (fence
->ops
->timeline_value_str
&&
86 fence
->ops
->fence_value_str
) {
90 fence
->ops
->fence_value_str(fence
, value
, sizeof(value
));
91 success
= strlen(value
);
94 seq_printf(s
, ": %s", value
);
96 fence
->ops
->timeline_value_str(fence
, value
,
100 seq_printf(s
, " / %s", value
);
107 static void sync_print_obj(struct seq_file
*s
, struct sync_timeline
*obj
)
109 struct list_head
*pos
;
111 seq_printf(s
, "%s: %d\n", obj
->name
, obj
->value
);
113 spin_lock_irq(&obj
->lock
);
114 list_for_each(pos
, &obj
->pt_list
) {
115 struct sync_pt
*pt
= container_of(pos
, struct sync_pt
, link
);
116 sync_print_fence(s
, &pt
->base
, false);
118 spin_unlock_irq(&obj
->lock
);
121 static void sync_print_sync_file(struct seq_file
*s
,
122 struct sync_file
*sync_file
)
127 seq_printf(s
, "[%p] %s: %s\n", sync_file
,
128 sync_file_get_name(sync_file
, buf
, sizeof(buf
)),
129 sync_status_str(dma_fence_get_status(sync_file
->fence
)));
131 if (dma_fence_is_array(sync_file
->fence
)) {
132 struct dma_fence_array
*array
= to_dma_fence_array(sync_file
->fence
);
134 for (i
= 0; i
< array
->num_fences
; ++i
)
135 sync_print_fence(s
, array
->fences
[i
], true);
137 sync_print_fence(s
, sync_file
->fence
, true);
141 static int sync_info_debugfs_show(struct seq_file
*s
, void *unused
)
143 struct list_head
*pos
;
145 seq_puts(s
, "objs:\n--------------\n");
147 spin_lock_irq(&sync_timeline_list_lock
);
148 list_for_each(pos
, &sync_timeline_list_head
) {
149 struct sync_timeline
*obj
=
150 container_of(pos
, struct sync_timeline
,
153 sync_print_obj(s
, obj
);
156 spin_unlock_irq(&sync_timeline_list_lock
);
158 seq_puts(s
, "fences:\n--------------\n");
160 spin_lock_irq(&sync_file_list_lock
);
161 list_for_each(pos
, &sync_file_list_head
) {
162 struct sync_file
*sync_file
=
163 container_of(pos
, struct sync_file
, sync_file_list
);
165 sync_print_sync_file(s
, sync_file
);
168 spin_unlock_irq(&sync_file_list_lock
);
172 DEFINE_SHOW_ATTRIBUTE(sync_info_debugfs
);
174 static __init
int sync_debugfs_init(void)
176 dbgfs
= debugfs_create_dir("sync", NULL
);
179 * The debugfs files won't ever get removed and thus, there is
180 * no need to protect it against removal races. The use of
181 * debugfs_create_file_unsafe() is actually safe here.
183 debugfs_create_file_unsafe("info", 0444, dbgfs
, NULL
,
184 &sync_info_debugfs_fops
);
185 debugfs_create_file_unsafe("sw_sync", 0644, dbgfs
, NULL
,
186 &sw_sync_debugfs_fops
);
190 late_initcall(sync_debugfs_init
);