xref: /OK3568_Linux_fs/kernel/drivers/dma-buf/sync_debug.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Sync File validation framework and debug information
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2012 Google, Inc.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/debugfs.h>
9*4882a593Smuzhiyun #include "sync_debug.h"
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun static struct dentry *dbgfs;
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun static LIST_HEAD(sync_timeline_list_head);
14*4882a593Smuzhiyun static DEFINE_SPINLOCK(sync_timeline_list_lock);
15*4882a593Smuzhiyun static LIST_HEAD(sync_file_list_head);
16*4882a593Smuzhiyun static DEFINE_SPINLOCK(sync_file_list_lock);
17*4882a593Smuzhiyun 
sync_timeline_debug_add(struct sync_timeline * obj)18*4882a593Smuzhiyun void sync_timeline_debug_add(struct sync_timeline *obj)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun 	unsigned long flags;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun 	spin_lock_irqsave(&sync_timeline_list_lock, flags);
23*4882a593Smuzhiyun 	list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head);
24*4882a593Smuzhiyun 	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun 
sync_timeline_debug_remove(struct sync_timeline * obj)27*4882a593Smuzhiyun void sync_timeline_debug_remove(struct sync_timeline *obj)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	unsigned long flags;
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	spin_lock_irqsave(&sync_timeline_list_lock, flags);
32*4882a593Smuzhiyun 	list_del(&obj->sync_timeline_list);
33*4882a593Smuzhiyun 	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
sync_file_debug_add(struct sync_file * sync_file)36*4882a593Smuzhiyun void sync_file_debug_add(struct sync_file *sync_file)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	unsigned long flags;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	spin_lock_irqsave(&sync_file_list_lock, flags);
41*4882a593Smuzhiyun 	list_add_tail(&sync_file->sync_file_list, &sync_file_list_head);
42*4882a593Smuzhiyun 	spin_unlock_irqrestore(&sync_file_list_lock, flags);
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun 
sync_file_debug_remove(struct sync_file * sync_file)45*4882a593Smuzhiyun void sync_file_debug_remove(struct sync_file *sync_file)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	unsigned long flags;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	spin_lock_irqsave(&sync_file_list_lock, flags);
50*4882a593Smuzhiyun 	list_del(&sync_file->sync_file_list);
51*4882a593Smuzhiyun 	spin_unlock_irqrestore(&sync_file_list_lock, flags);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
sync_status_str(int status)54*4882a593Smuzhiyun static const char *sync_status_str(int status)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	if (status < 0)
57*4882a593Smuzhiyun 		return "error";
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	if (status > 0)
60*4882a593Smuzhiyun 		return "signaled";
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	return "active";
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun 
sync_print_fence(struct seq_file * s,struct dma_fence * fence,bool show)65*4882a593Smuzhiyun static void sync_print_fence(struct seq_file *s,
66*4882a593Smuzhiyun 			     struct dma_fence *fence, bool show)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	struct sync_timeline *parent = dma_fence_parent(fence);
69*4882a593Smuzhiyun 	int status;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	status = dma_fence_get_status_locked(fence);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	seq_printf(s, "  %s%sfence %s",
74*4882a593Smuzhiyun 		   show ? parent->name : "",
75*4882a593Smuzhiyun 		   show ? "_" : "",
76*4882a593Smuzhiyun 		   sync_status_str(status));
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags)) {
79*4882a593Smuzhiyun 		struct timespec64 ts64 =
80*4882a593Smuzhiyun 			ktime_to_timespec64(fence->timestamp);
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 		seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	if (fence->ops->timeline_value_str &&
86*4882a593Smuzhiyun 		fence->ops->fence_value_str) {
87*4882a593Smuzhiyun 		char value[64];
88*4882a593Smuzhiyun 		bool success;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 		fence->ops->fence_value_str(fence, value, sizeof(value));
91*4882a593Smuzhiyun 		success = strlen(value);
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 		if (success) {
94*4882a593Smuzhiyun 			seq_printf(s, ": %s", value);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 			fence->ops->timeline_value_str(fence, value,
97*4882a593Smuzhiyun 						       sizeof(value));
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 			if (strlen(value))
100*4882a593Smuzhiyun 				seq_printf(s, " / %s", value);
101*4882a593Smuzhiyun 		}
102*4882a593Smuzhiyun 	}
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	seq_putc(s, '\n');
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
sync_print_obj(struct seq_file * s,struct sync_timeline * obj)107*4882a593Smuzhiyun static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	struct list_head *pos;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	seq_printf(s, "%s: %d\n", obj->name, obj->value);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	spin_lock_irq(&obj->lock);
114*4882a593Smuzhiyun 	list_for_each(pos, &obj->pt_list) {
115*4882a593Smuzhiyun 		struct sync_pt *pt = container_of(pos, struct sync_pt, link);
116*4882a593Smuzhiyun 		sync_print_fence(s, &pt->base, false);
117*4882a593Smuzhiyun 	}
118*4882a593Smuzhiyun 	spin_unlock_irq(&obj->lock);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
sync_print_sync_file(struct seq_file * s,struct sync_file * sync_file)121*4882a593Smuzhiyun static void sync_print_sync_file(struct seq_file *s,
122*4882a593Smuzhiyun 				  struct sync_file *sync_file)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	char buf[128];
125*4882a593Smuzhiyun 	int i;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	seq_printf(s, "[%p] %s: %s\n", sync_file,
128*4882a593Smuzhiyun 		   sync_file_get_name(sync_file, buf, sizeof(buf)),
129*4882a593Smuzhiyun 		   sync_status_str(dma_fence_get_status(sync_file->fence)));
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	if (dma_fence_is_array(sync_file->fence)) {
132*4882a593Smuzhiyun 		struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 		for (i = 0; i < array->num_fences; ++i)
135*4882a593Smuzhiyun 			sync_print_fence(s, array->fences[i], true);
136*4882a593Smuzhiyun 	} else {
137*4882a593Smuzhiyun 		sync_print_fence(s, sync_file->fence, true);
138*4882a593Smuzhiyun 	}
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
sync_info_debugfs_show(struct seq_file * s,void * unused)141*4882a593Smuzhiyun static int sync_info_debugfs_show(struct seq_file *s, void *unused)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	struct list_head *pos;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	seq_puts(s, "objs:\n--------------\n");
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	spin_lock_irq(&sync_timeline_list_lock);
148*4882a593Smuzhiyun 	list_for_each(pos, &sync_timeline_list_head) {
149*4882a593Smuzhiyun 		struct sync_timeline *obj =
150*4882a593Smuzhiyun 			container_of(pos, struct sync_timeline,
151*4882a593Smuzhiyun 				     sync_timeline_list);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 		sync_print_obj(s, obj);
154*4882a593Smuzhiyun 		seq_putc(s, '\n');
155*4882a593Smuzhiyun 	}
156*4882a593Smuzhiyun 	spin_unlock_irq(&sync_timeline_list_lock);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	seq_puts(s, "fences:\n--------------\n");
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	spin_lock_irq(&sync_file_list_lock);
161*4882a593Smuzhiyun 	list_for_each(pos, &sync_file_list_head) {
162*4882a593Smuzhiyun 		struct sync_file *sync_file =
163*4882a593Smuzhiyun 			container_of(pos, struct sync_file, sync_file_list);
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 		sync_print_sync_file(s, sync_file);
166*4882a593Smuzhiyun 		seq_putc(s, '\n');
167*4882a593Smuzhiyun 	}
168*4882a593Smuzhiyun 	spin_unlock_irq(&sync_file_list_lock);
169*4882a593Smuzhiyun 	return 0;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(sync_info_debugfs);
173*4882a593Smuzhiyun 
sync_debugfs_init(void)174*4882a593Smuzhiyun static __init int sync_debugfs_init(void)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun 	dbgfs = debugfs_create_dir("sync", NULL);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	/*
179*4882a593Smuzhiyun 	 * The debugfs files won't ever get removed and thus, there is
180*4882a593Smuzhiyun 	 * no need to protect it against removal races. The use of
181*4882a593Smuzhiyun 	 * debugfs_create_file_unsafe() is actually safe here.
182*4882a593Smuzhiyun 	 */
183*4882a593Smuzhiyun 	debugfs_create_file_unsafe("info", 0444, dbgfs, NULL,
184*4882a593Smuzhiyun 				   &sync_info_debugfs_fops);
185*4882a593Smuzhiyun 	debugfs_create_file_unsafe("sw_sync", 0644, dbgfs, NULL,
186*4882a593Smuzhiyun 				   &sw_sync_debugfs_fops);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	return 0;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun late_initcall(sync_debugfs_init);
191