blob: 101394f16930f81f1ac98da172a50517e7534cff [file] [log] [blame]
Thomas Gleixner9c92ab62019-05-29 07:17:56 -07001// SPDX-License-Identifier: GPL-2.0-only
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +02002/*
Gustavo Padovane912c882016-08-11 12:26:42 -03003 * Sync File validation framework and debug information
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +02004 *
5 * Copyright (C) 2012 Google, Inc.
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +02006 */
7
8#include <linux/debugfs.h>
Gustavo Padovan1fe82e22016-05-31 16:59:12 -03009#include "sync_debug.h"
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020010
Gustavo Padovan8a004482016-01-21 10:49:17 -020011static struct dentry *dbgfs;
12
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020013static LIST_HEAD(sync_timeline_list_head);
14static DEFINE_SPINLOCK(sync_timeline_list_lock);
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -020015static LIST_HEAD(sync_file_list_head);
16static DEFINE_SPINLOCK(sync_file_list_lock);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020017
18void sync_timeline_debug_add(struct sync_timeline *obj)
19{
20 unsigned long flags;
21
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);
25}
26
27void sync_timeline_debug_remove(struct sync_timeline *obj)
28{
29 unsigned long flags;
30
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);
34}
35
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -020036void sync_file_debug_add(struct sync_file *sync_file)
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020037{
38 unsigned long flags;
39
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -020040 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);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020043}
44
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -020045void sync_file_debug_remove(struct sync_file *sync_file)
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020046{
47 unsigned long flags;
48
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -020049 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);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020052}
53
54static const char *sync_status_str(int status)
55{
Chris Wilsond6c99f42017-01-04 14:12:21 +000056 if (status < 0)
57 return "error";
Peter Senna Tschudin95451352014-07-12 21:55:56 +020058
59 if (status > 0)
Chris Wilsond6c99f42017-01-04 14:12:21 +000060 return "signaled";
Peter Senna Tschudin95451352014-07-12 21:55:56 +020061
Chris Wilsond6c99f42017-01-04 14:12:21 +000062 return "active";
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020063}
64
Chris Wilsonf54d1862016-10-25 13:00:45 +010065static void sync_print_fence(struct seq_file *s,
66 struct dma_fence *fence, bool show)
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020067{
Chris Wilsonf54d1862016-10-25 13:00:45 +010068 struct sync_timeline *parent = dma_fence_parent(fence);
Chris Wilsond6c99f42017-01-04 14:12:21 +000069 int status;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020070
Chris Wilsond6c99f42017-01-04 14:12:21 +000071 status = dma_fence_get_status_locked(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020072
Gustavo Padovanb55b54b2016-01-21 10:49:21 -020073 seq_printf(s, " %s%sfence %s",
74 show ? parent->name : "",
75 show ? "_" : "",
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020076 sync_status_str(status));
77
Chris Wilson76250f22017-02-14 12:40:01 +000078 if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags)) {
Steve Pennington0541cdf2014-12-24 09:33:02 -060079 struct timespec64 ts64 =
Gustavo Padovanb55b54b2016-01-21 10:49:21 -020080 ktime_to_timespec64(fence->timestamp);
Peter Senna Tschudin95451352014-07-12 21:55:56 +020081
Tapasweni Pathak353fdf12014-10-26 19:20:16 +053082 seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020083 }
84
Gustavo Padovan724812d62016-05-31 16:59:02 -030085 if (fence->ops->timeline_value_str &&
Gustavo Padovanb55b54b2016-01-21 10:49:21 -020086 fence->ops->fence_value_str) {
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020087 char value[64];
Maarten Lankhorst73465f12015-12-11 13:11:49 +000088 bool success;
Peter Senna Tschudin95451352014-07-12 21:55:56 +020089
Gustavo Padovanb55b54b2016-01-21 10:49:21 -020090 fence->ops->fence_value_str(fence, value, sizeof(value));
Maarten Lankhorst73465f12015-12-11 13:11:49 +000091 success = strlen(value);
92
Gustavo Padovan724812d62016-05-31 16:59:02 -030093 if (success) {
Maarten Lankhorst73465f12015-12-11 13:11:49 +000094 seq_printf(s, ": %s", value);
95
Gustavo Padovanb55b54b2016-01-21 10:49:21 -020096 fence->ops->timeline_value_str(fence, value,
97 sizeof(value));
Maarten Lankhorst73465f12015-12-11 13:11:49 +000098
99 if (strlen(value))
100 seq_printf(s, " / %s", value);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200101 }
102 }
103
Markus Elfring47a369d2017-05-08 10:55:42 +0200104 seq_putc(s, '\n');
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200105}
106
107static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
108{
109 struct list_head *pos;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200110
Gustavo Padovanb9bc2b72016-05-31 16:59:11 -0300111 seq_printf(s, "%s: %d\n", obj->name, obj->value);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200112
Chris Wilsond3862e42017-06-29 22:05:32 +0100113 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);
Gustavo Padovan0431b902016-05-31 16:59:04 -0300116 sync_print_fence(s, &pt->base, false);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200117 }
Chris Wilsond3862e42017-06-29 22:05:32 +0100118 spin_unlock_irq(&obj->lock);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200119}
120
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200121static void sync_print_sync_file(struct seq_file *s,
122 struct sync_file *sync_file)
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200123{
Chris Wilson71ebc9a2017-05-16 12:10:42 +0100124 char buf[128];
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200125 int i;
126
Chris Wilson71ebc9a2017-05-16 12:10:42 +0100127 seq_printf(s, "[%p] %s: %s\n", sync_file,
128 sync_file_get_name(sync_file, buf, sizeof(buf)),
Chris Wilsond6c99f42017-01-04 14:12:21 +0000129 sync_status_str(dma_fence_get_status(sync_file->fence)));
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200130
Chris Wilsonf54d1862016-10-25 13:00:45 +0100131 if (dma_fence_is_array(sync_file->fence)) {
132 struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
Linus Torvalds6b25e212016-10-11 18:12:22 -0700133
134 for (i = 0; i < array->num_fences; ++i)
135 sync_print_fence(s, array->fences[i], true);
136 } else {
137 sync_print_fence(s, sync_file->fence, true);
138 }
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200139}
140
Yangtao Li26743052018-11-30 11:11:01 -0500141static int sync_info_debugfs_show(struct seq_file *s, void *unused)
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200142{
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200143 struct list_head *pos;
144
145 seq_puts(s, "objs:\n--------------\n");
146
Chris Wilsona6aa8fc2017-06-29 13:59:27 +0100147 spin_lock_irq(&sync_timeline_list_lock);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200148 list_for_each(pos, &sync_timeline_list_head) {
149 struct sync_timeline *obj =
150 container_of(pos, struct sync_timeline,
151 sync_timeline_list);
152
153 sync_print_obj(s, obj);
Markus Elfring47a369d2017-05-08 10:55:42 +0200154 seq_putc(s, '\n');
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200155 }
Chris Wilsona6aa8fc2017-06-29 13:59:27 +0100156 spin_unlock_irq(&sync_timeline_list_lock);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200157
158 seq_puts(s, "fences:\n--------------\n");
159
Chris Wilsona6aa8fc2017-06-29 13:59:27 +0100160 spin_lock_irq(&sync_file_list_lock);
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200161 list_for_each(pos, &sync_file_list_head) {
162 struct sync_file *sync_file =
163 container_of(pos, struct sync_file, sync_file_list);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200164
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200165 sync_print_sync_file(s, sync_file);
Markus Elfring47a369d2017-05-08 10:55:42 +0200166 seq_putc(s, '\n');
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200167 }
Chris Wilsona6aa8fc2017-06-29 13:59:27 +0100168 spin_unlock_irq(&sync_file_list_lock);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200169 return 0;
170}
171
Yangtao Li26743052018-11-30 11:11:01 -0500172DEFINE_SHOW_ATTRIBUTE(sync_info_debugfs);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200173
174static __init int sync_debugfs_init(void)
175{
Gustavo Padovan8a004482016-01-21 10:49:17 -0200176 dbgfs = debugfs_create_dir("sync", NULL);
177
Nicolai Stange0fd9da92016-05-27 20:03:54 +0200178 /*
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.
182 */
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);
Gustavo Padovan8a004482016-01-21 10:49:17 -0200187
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200188 return 0;
189}
190late_initcall(sync_debugfs_init);