[RFC 24/29] dma-buf/fence: add debug to fence timeline

From: Gustavo Padovan
Date: Fri Jan 15 2016 - 09:57:25 EST


From: Gustavo Padovan <gustavo.padovan@xxxxxxxxxxxxxxx>

Bring the debug information that belonged to sync_timeline and sync_pt
back.

Signed-off-by: Gustavo Padovan <gustavo.padovan@xxxxxxxxxxxxxxx>
---
drivers/dma-buf/Makefile | 2 +-
drivers/dma-buf/fence.c | 4 ++
drivers/dma-buf/fence_debug.c | 128 +++++++++++++++++++++++++++++++++++
drivers/staging/android/sync.h | 4 --
drivers/staging/android/sync_debug.c | 105 +---------------------------
include/linux/fence.h | 18 +++++
6 files changed, 154 insertions(+), 107 deletions(-)
create mode 100644 drivers/dma-buf/fence_debug.c

diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 57a675f..fb03696 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1 +1 @@
-obj-y := dma-buf.o fence.o reservation.o seqno-fence.o
+obj-y := dma-buf.o fence.o fence_debug.o reservation.o seqno-fence.o
diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c
index 0a07fcb..09faf2e 100644
--- a/drivers/dma-buf/fence.c
+++ b/drivers/dma-buf/fence.c
@@ -84,6 +84,8 @@ struct fence_timeline *fence_timeline_create(unsigned num, int size,
INIT_LIST_HEAD(&timeline->active_list_head);
spin_lock_init(&timeline->lock);

+ fence_timeline_debug_add(timeline);
+
return timeline;
}
EXPORT_SYMBOL(fence_timeline_create);
@@ -100,6 +102,8 @@ static void fence_timeline_free(struct kref *kref)
struct fence_timeline *timeline =
container_of(kref, struct fence_timeline, kref);

+ fence_timeline_debug_remove(timeline);
+
kfree(timeline);
}

diff --git a/drivers/dma-buf/fence_debug.c b/drivers/dma-buf/fence_debug.c
new file mode 100644
index 0000000..c7529c6
--- /dev/null
+++ b/drivers/dma-buf/fence_debug.c
@@ -0,0 +1,128 @@
+/*
+ * drivers/dma-buf/fence_debug.c
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/seq_file.h>
+#include <linux/fence.h>
+
+#ifdef CONFIG_DEBUG_FS
+
+static LIST_HEAD(fence_timeline_list_head);
+static DEFINE_SPINLOCK(fence_timeline_list_lock);
+
+void fence_timeline_debug_add(struct fence_timeline *obj)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fence_timeline_list_lock, flags);
+ list_add_tail(&obj->fence_timeline_list, &fence_timeline_list_head);
+ spin_unlock_irqrestore(&fence_timeline_list_lock, flags);
+}
+EXPORT_SYMBOL(fence_timeline_debug_add);
+
+void fence_timeline_debug_remove(struct fence_timeline *obj)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fence_timeline_list_lock, flags);
+ list_del(&obj->fence_timeline_list);
+ spin_unlock_irqrestore(&fence_timeline_list_lock, flags);
+}
+EXPORT_SYMBOL(fence_timeline_debug_remove);
+
+const char *fence_status_str(int status)
+{
+ if (status == 0)
+ return "signaled";
+
+ if (status > 0)
+ return "active";
+
+ return "error";
+}
+EXPORT_SYMBOL(fence_status_str);
+
+void fence_print(struct seq_file *s, struct fence *fence, bool show)
+{
+ int status = 1;
+ struct fence_timeline *parent = fence_parent(fence);
+
+ if (fence_is_signaled_locked(fence))
+ status = fence->status;
+
+ seq_printf(s, " %s%sfence %s",
+ show ? parent->name : "",
+ show ? "_" : "",
+ fence_status_str(status));
+
+ if (status <= 0) {
+ struct timespec64 ts64 =
+ ktime_to_timespec64(fence->timestamp);
+
+ seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
+ }
+
+ if (fence->ops->timeline_value_str &&
+ fence->ops->fence_value_str) {
+ char value[64];
+
+ fence->ops->fence_value_str(fence, value, sizeof(value));
+ seq_printf(s, ": %s", value);
+ if (show) {
+ fence->ops->timeline_value_str(fence, value,
+ sizeof(value));
+ seq_printf(s, " / %s", value);
+ }
+ }
+
+ seq_puts(s, "\n");
+}
+EXPORT_SYMBOL(fence_print);
+
+void fence_timeline_print(struct seq_file *s, struct fence_timeline *obj)
+{
+ struct list_head *pos;
+ unsigned long flags;
+
+ seq_printf(s, "%s %s: %u\n", obj->name, obj->drv_name, obj->value);
+
+ spin_lock_irqsave(&obj->lock, flags);
+ list_for_each(pos, &obj->child_list_head) {
+ struct fence *fence =
+ container_of(pos, struct fence, child_list);
+ fence_print(s, fence, false);
+ }
+ spin_unlock_irqrestore(&obj->lock, flags);
+}
+EXPORT_SYMBOL(fence_timeline_print);
+
+void fence_timeline_print_all(struct seq_file* s)
+{
+ unsigned long flags;
+ struct list_head *pos;
+
+ spin_lock_irqsave(&fence_timeline_list_lock, flags);
+ list_for_each(pos, &fence_timeline_list_head) {
+ struct fence_timeline *obj =
+ container_of(pos, struct fence_timeline,
+ fence_timeline_list);
+
+ fence_timeline_print(s, obj);
+ seq_puts(s, "\n");
+ }
+ spin_unlock_irqrestore(&fence_timeline_list_lock, flags);
+}
+EXPORT_SYMBOL(fence_timeline_print_all);
+#endif
diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h
index 256315c..8e6827b 100644
--- a/drivers/staging/android/sync.h
+++ b/drivers/staging/android/sync.h
@@ -184,15 +184,11 @@ int sync_fence_wait(struct sync_fence *fence, long timeout);

#ifdef CONFIG_DEBUG_FS

-void sync_timeline_debug_add(struct fence_timeline *obj);
-void sync_timeline_debug_remove(struct fence_timeline *obj);
void sync_fence_debug_add(struct sync_fence *fence);
void sync_fence_debug_remove(struct sync_fence *fence);
void sync_dump(void);

#else
-# define sync_timeline_debug_add(obj)
-# define sync_timeline_debug_remove(obj)
# define sync_fence_debug_add(fence)
# define sync_fence_debug_remove(fence)
# define sync_dump()
diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c
index 13d225f..8e2ca57 100644
--- a/drivers/staging/android/sync_debug.c
+++ b/drivers/staging/android/sync_debug.c
@@ -33,29 +33,9 @@

static struct dentry *dbgfs;

-static LIST_HEAD(sync_timeline_list_head);
-static DEFINE_SPINLOCK(sync_timeline_list_lock);
static LIST_HEAD(sync_fence_list_head);
static DEFINE_SPINLOCK(sync_fence_list_lock);

-void sync_timeline_debug_add(struct fence_timeline *obj)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&sync_timeline_list_lock, flags);
- list_add_tail(&obj->fence_timeline_list, &sync_timeline_list_head);
- spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
-}
-
-void sync_timeline_debug_remove(struct fence_timeline *obj)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&sync_timeline_list_lock, flags);
- list_del(&obj->fence_timeline_list);
- spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
-}
-
void sync_fence_debug_add(struct sync_fence *sync_fence)
{
unsigned long flags;
@@ -74,76 +54,6 @@ void sync_fence_debug_remove(struct sync_fence *sync_fence)
spin_unlock_irqrestore(&sync_fence_list_lock, flags);
}

-static const char *sync_status_str(int status)
-{
- if (status == 0)
- return "signaled";
-
- if (status > 0)
- return "active";
-
- return "error";
-}
-
-static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show)
-{
- int status = 1;
- struct fence_timeline *parent = fence_parent(fence);
-
- if (fence_is_signaled_locked(fence))
- status = fence->status;
-
- seq_printf(s, " %s%sfence %s",
- show ? parent->name : "",
- show ? "_" : "",
- sync_status_str(status));
-
- if (status <= 0) {
- struct timespec64 ts64 =
- ktime_to_timespec64(fence->timestamp);
-
- seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
- }
-
- if ((!fence || fence->ops->timeline_value_str) &&
- fence->ops->fence_value_str) {
- char value[64];
- bool success;
-
- fence->ops->fence_value_str(fence, value, sizeof(value));
- success = strlen(value);
-
- if (success)
- seq_printf(s, ": %s", value);
-
- if (success && fence) {
- fence->ops->timeline_value_str(fence, value,
- sizeof(value));
-
- if (strlen(value))
- seq_printf(s, " / %s", value);
- }
- }
-
- seq_puts(s, "\n");
-}
-
-static void sync_print_obj(struct seq_file *s, struct fence_timeline *obj)
-{
- struct list_head *pos;
- unsigned long flags;
-
- seq_printf(s, "%s %s: %d\n", obj->name, obj->drv_name, obj->value);
-
- spin_lock_irqsave(&obj->lock, flags);
- list_for_each(pos, &obj->child_list_head) {
- struct fence *fence =
- container_of(pos, struct fence, child_list);
- sync_print_fence(s, fence, false);
- }
- spin_unlock_irqrestore(&obj->lock, flags);
-}
-
static void sync_print_sync_fence(struct seq_file *s,
struct sync_fence *sync_fence)
{
@@ -152,10 +62,10 @@ static void sync_print_sync_fence(struct seq_file *s,
int i;

seq_printf(s, "[%p] %s: %s\n", sync_fence, sync_fence->name,
- sync_status_str(atomic_read(&sync_fence->status)));
+ fence_status_str(atomic_read(&sync_fence->status)));

for (i = 0; i < sync_fence->num_fences; ++i) {
- sync_print_fence(s, sync_fence->cbs[i].fence, true);
+ fence_print(s, sync_fence->cbs[i].fence, true);
}

spin_lock_irqsave(&sync_fence->wq.lock, flags);
@@ -179,16 +89,7 @@ static int sync_debugfs_show(struct seq_file *s, void *unused)

seq_puts(s, "objs:\n--------------\n");

- spin_lock_irqsave(&sync_timeline_list_lock, flags);
- list_for_each(pos, &sync_timeline_list_head) {
- struct fence_timeline *obj =
- container_of(pos, struct fence_timeline,
- fence_timeline_list);
-
- sync_print_obj(s, obj);
- seq_puts(s, "\n");
- }
- spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+ fence_timeline_print_all(s);

seq_puts(s, "fences:\n--------------\n");

diff --git a/include/linux/fence.h b/include/linux/fence.h
index adece43..32a26ab 100644
--- a/include/linux/fence.h
+++ b/include/linux/fence.h
@@ -407,6 +407,24 @@ static inline signed long fence_wait(struct fence *fence, bool intr)

unsigned fence_context_alloc(unsigned num);

+#ifdef CONFIG_DEBUG_FS
+
+void fence_timeline_debug_add(struct fence_timeline *obj);
+void fence_timeline_debug_remove(struct fence_timeline *obj);
+const char *fence_status_str(int status);
+void fence_print(struct seq_file *s, struct fence *fence, bool show);
+void fence_timeline_print(struct seq_file *s, struct fence_timeline *obj);
+void fence_timeline_print_all(struct seq_file* s);
+
+#else
+#define fence_timeline_debug_add(obj)
+#define fence_timeline_debug_remove(obj)
+#define fence_status_str(status)
+#define fence_print(s, fence, show)
+#define fence_timeline_print(s, obj)
+#define fence_timeline_print_all(s)
+#endif
+
#define FENCE_TRACE(f, fmt, args...) \
do { \
struct fence *__ff = (f); \
--
2.5.0