File Index
Files and directories
Sign in
FILE

sync_debug.c

File preview with syntax highlighting.

linux-6.19.14/drivers/dma-buf/sync_debug.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Sync File validation framework and debug information
  4 *
  5 * Copyright (C) 2012 Google, Inc.
  6 */
  7
  8#include <linux/debugfs.h>
  9#include "sync_debug.h"
 10
 11static struct dentry *dbgfs;
 12
 13static LIST_HEAD(sync_timeline_list_head);
 14static DEFINE_SPINLOCK(sync_timeline_list_lock);
 15
 16void sync_timeline_debug_add(struct sync_timeline *obj)
 17{
 18	unsigned long flags;
 19
 20	spin_lock_irqsave(&sync_timeline_list_lock, flags);
 21	list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head);
 22	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
 23}
 24
 25void sync_timeline_debug_remove(struct sync_timeline *obj)
 26{
 27	unsigned long flags;
 28
 29	spin_lock_irqsave(&sync_timeline_list_lock, flags);
 30	list_del(&obj->sync_timeline_list);
 31	spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
 32}
 33
 34static const char *sync_status_str(int status)
 35{
 36	if (status < 0)
 37		return "error";
 38
 39	if (status > 0)
 40		return "signaled";
 41
 42	return "active";
 43}
 44
 45static void sync_print_fence(struct seq_file *s,
 46			     struct dma_fence *fence, bool show)
 47{
 48	struct sync_timeline *parent = dma_fence_parent(fence);
 49	int status;
 50
 51	status = dma_fence_get_status_locked(fence);
 52
 53	seq_printf(s, "  %s%sfence %s",
 54		   show ? parent->name : "",
 55		   show ? "_" : "",
 56		   sync_status_str(status));
 57
 58	if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags)) {
 59		struct timespec64 ts64 =
 60			ktime_to_timespec64(fence->timestamp);
 61
 62		seq_printf(s, "@%ptSp", &ts64);
 63	}
 64
 65	seq_printf(s, ": %lld", fence->seqno);
 66	seq_printf(s, " / %d", parent->value);
 67	seq_putc(s, '\n');
 68}
 69
 70static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
 71{
 72	struct list_head *pos;
 73
 74	seq_printf(s, "%s: %d\n", obj->name, obj->value);
 75
 76	spin_lock(&obj->lock); /* Caller already disabled IRQ. */
 77	list_for_each(pos, &obj->pt_list) {
 78		struct sync_pt *pt = container_of(pos, struct sync_pt, link);
 79		sync_print_fence(s, &pt->base, false);
 80	}
 81	spin_unlock(&obj->lock);
 82}
 83
 84static int sync_info_debugfs_show(struct seq_file *s, void *unused)
 85{
 86	struct list_head *pos;
 87
 88	seq_puts(s, "objs:\n--------------\n");
 89
 90	spin_lock_irq(&sync_timeline_list_lock);
 91	list_for_each(pos, &sync_timeline_list_head) {
 92		struct sync_timeline *obj =
 93			container_of(pos, struct sync_timeline,
 94				     sync_timeline_list);
 95
 96		sync_print_obj(s, obj);
 97		seq_putc(s, '\n');
 98	}
 99	spin_unlock_irq(&sync_timeline_list_lock);
100
101	seq_puts(s, "fences:\n--------------\n");
102
103	return 0;
104}
105
106DEFINE_SHOW_ATTRIBUTE(sync_info_debugfs);
107
108static __init int sync_debugfs_init(void)
109{
110	dbgfs = debugfs_create_dir("sync", NULL);
111
112	/*
113	 * The debugfs files won't ever get removed and thus, there is
114	 * no need to protect it against removal races. The use of
115	 * debugfs_create_file_unsafe() is actually safe here.
116	 */
117	debugfs_create_file_unsafe("info", 0444, dbgfs, NULL,
118				   &sync_info_debugfs_fops);
119	debugfs_create_file_unsafe("sw_sync", 0644, dbgfs, NULL,
120				   &sw_sync_debugfs_fops);
121
122	return 0;
123}
124late_initcall(sync_debugfs_init);
~/ Read-only file preview.