diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu
index 8a608ca44..b8a3f0331 100644
--- a/drivers/gpu/nvgpu/Makefile.nvgpu
+++ b/drivers/gpu/nvgpu/Makefile.nvgpu
@@ -30,6 +30,7 @@ nvgpu-y := \
common/linux/ioctl_as.o \
common/linux/ioctl_channel.o \
common/linux/ioctl_tsg.o \
+ common/linux/log.o \
common/mm/nvgpu_allocator.o \
common/mm/bitmap_allocator.o \
common/mm/buddy_allocator.o \
diff --git a/drivers/gpu/nvgpu/common/linux/log.c b/drivers/gpu/nvgpu/common/linux/log.c
new file mode 100644
index 000000000..9dd965ec8
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/log.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+#include
+
+#include "gk20a/gk20a.h"
+
+/*
+ * Define a length for log buffers. This is the buffer that the 'fmt, ...' part
+ * of __nvgpu_do_log_print() prints into. This buffer lives on the stack so it
+ * needs to not be overly sized since we have limited kernel stack space. But at
+ * the same time we don't want it to be restrictive either.
+ */
+#define LOG_BUFFER_LENGTH 160
+
+/*
+ * Annoying quirk of Linux: this has to be a string literal since the printk()
+ * function and friends use the preprocessor to concatenate stuff to the start
+ * of this string when printing.
+ */
+#define LOG_FMT "nvgpu: %s %33s:%-4d [%s] %s"
+
+u32 nvgpu_dbg_mask = NVGPU_DEFAULT_DBG_MASK;
+
+static const char *log_types[] = {
+ "ERR",
+ "WRN",
+ "DBG"
+};
+
+int nvgpu_log_mask_enabled(struct gk20a *g, u32 log_mask)
+{
+ return !!(g->log_mask & log_mask);
+}
+
+static inline const char *nvgpu_log_name(struct gk20a *g)
+{
+ return dev_name(g->dev);
+}
+
+#ifdef CONFIG_GK20A_TRACE_PRINTK
+static void __nvgpu_trace_printk_log(u32 trace, const char *gpu_name,
+ const char *func_name, int line,
+ enum nvgpu_log_type type, const char *log)
+{
+ trace_printk(LOG_FMT, gpu_name, func_name, line, type, log);
+}
+#endif
+
+static void __nvgpu_really_print_log(u32 trace, const char *gpu_name,
+ const char *func_name, int line,
+ enum nvgpu_log_type type, const char *log)
+{
+ const char *name = gpu_name ? gpu_name : "";
+
+#ifdef CONFIG_GK20A_TRACE_PRINTK
+ if (trace)
+ return __nvgpu_trace_printk_log(trace, name, func_name,
+ line, type, log);
+#else
+ const char *log_type = log_types[type];
+
+ switch (type) {
+ case DEBUG:
+ /*
+ * We could use pr_debug() here but we control debug enablement
+ * separately from the Linux kernel. Perhaps this is a bug in
+ * nvgpu.
+ */
+ pr_info(LOG_FMT, name, func_name, line, log_type, log);
+ break;
+ case WARNING:
+ pr_warn(LOG_FMT, name, func_name, line, log_type, log);
+ break;
+ case ERROR:
+ pr_err(LOG_FMT, name, func_name, line, log_type, log);
+ break;
+ }
+#endif
+}
+
+__attribute__((format (printf, 5, 6)))
+void __nvgpu_log_msg(struct gk20a *g, const char *func_name, int line,
+ enum nvgpu_log_type type, const char *fmt, ...)
+{
+ char log[LOG_BUFFER_LENGTH];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(log, LOG_BUFFER_LENGTH, fmt, args);
+ va_end(args);
+
+ __nvgpu_really_print_log(0, g ? nvgpu_log_name(g) : "",
+ func_name, line, type, log);
+}
+
+__attribute__((format (printf, 5, 6)))
+void __nvgpu_log_dbg(struct gk20a *g, u32 log_mask,
+ const char *func_name, int line,
+ const char *fmt, ...)
+{
+ char log[LOG_BUFFER_LENGTH];
+ va_list args;
+
+ if ((log_mask & g->log_mask) == 0)
+ return;
+
+ va_start(args, fmt);
+ vsnprintf(log, LOG_BUFFER_LENGTH, fmt, args);
+ va_end(args);
+
+ __nvgpu_really_print_log(g->log_trace, nvgpu_log_name(g),
+ func_name, line, DEBUG, log);
+}
diff --git a/drivers/gpu/nvgpu/gk20a/debug_gk20a.c b/drivers/gpu/nvgpu/gk20a/debug_gk20a.c
index b666bb167..a8b9c5fb6 100644
--- a/drivers/gpu/nvgpu/gk20a/debug_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/debug_gk20a.c
@@ -16,8 +16,9 @@
#include
#include
-#include
+#include
#include
+#include
#include "gk20a.h"
#include "debug_gk20a.h"
@@ -232,7 +233,6 @@ void gk20a_debug_init(struct device *dev, const char *debugfs_symlink)
struct gk20a_platform *platform = dev_get_drvdata(dev);
#ifdef CONFIG_DEBUG_FS
struct gk20a *g = platform->g;
-#endif
platform->debugfs = debugfs_create_dir(dev_name(dev), NULL);
if (!platform->debugfs)
@@ -256,15 +256,16 @@ void gk20a_debug_init(struct device *dev, const char *debugfs_symlink)
debugfs_create_bool("disable_syncpoints", S_IRUGO|S_IWUSR,
platform->debugfs, &platform->disable_syncpoints);
+ /* Legacy debugging API. */
debugfs_create_u32("dbg_mask", S_IRUGO|S_IWUSR,
- platform->debugfs, &gk20a_dbg_mask);
+ platform->debugfs, &nvgpu_dbg_mask);
-#ifdef CONFIG_GK20A_TRACE_PRINTK
- debugfs_create_u32("dbg_ftrace", S_IRUGO|S_IWUSR,
- platform->debugfs, &gk20a_dbg_ftrace);
-#endif
+ /* New debug logging API. */
+ debugfs_create_u32("log_mask", S_IRUGO|S_IWUSR,
+ platform->debugfs, &g->log_mask);
+ debugfs_create_u32("log_trace", S_IRUGO|S_IWUSR,
+ platform->debugfs, &g->log_trace);
-#ifdef CONFIG_DEBUG_FS
nvgpu_spinlock_init(&g->debugfs_lock);
g->mm.ltc_enabled = true;
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index 6d80f3bab..c8acf6f7b 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -82,11 +82,6 @@
#define GK20A_NUM_CDEVS 7
-u32 gk20a_dbg_mask = GK20A_DEFAULT_DBG_MASK;
-#ifdef CONFIG_GK20A_TRACE_PRINTK
-u32 gk20a_dbg_ftrace;
-#endif
-
#define GK20A_WAIT_FOR_IDLE_MS 2000
static int gk20a_pm_prepare_poweroff(struct device *dev);
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index ec27ed77e..2a9f8a069 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -41,9 +41,10 @@ struct dbg_profiler_object_data;
#include "../../../arch/arm/mach-tegra/iomap.h"
+#include
+#include
#include
#include
-#include
#include "clk_gk20a.h"
#include "ce2_gk20a.h"
@@ -927,6 +928,9 @@ struct gk20a {
bool power_on;
bool suspended;
+ u32 log_mask;
+ u32 log_trace;
+
struct rw_semaphore busy_lock;
struct clk_gk20a clk;
@@ -1193,89 +1197,12 @@ struct gk20a_cyclestate_buffer_elem {
u64 data;
};
-/* debug accessories */
-
-#ifdef CONFIG_DEBUG_FS
- /* debug info, default is compiled-in but effectively disabled (0 mask) */
- /*e.g: echo 1 > /d/gk20a.0/dbg_mask */
- #define GK20A_DEFAULT_DBG_MASK 0
-#else
- /* manually enable and turn it on the mask */
- #define GK20A_DEFAULT_DBG_MASK (dbg_info)
-#endif
-
-enum gk20a_dbg_categories {
- gpu_dbg_info = BIT(0), /* lightly verbose info */
- gpu_dbg_fn = BIT(2), /* fn name tracing */
- gpu_dbg_reg = BIT(3), /* register accesses, very verbose */
- gpu_dbg_pte = BIT(4), /* gmmu ptes */
- gpu_dbg_intr = BIT(5), /* interrupts */
- gpu_dbg_pmu = BIT(6), /* gk20a pmu */
- gpu_dbg_clk = BIT(7), /* gk20a clk */
- gpu_dbg_map = BIT(8), /* mem mappings */
- gpu_dbg_gpu_dbg = BIT(9), /* gpu debugger/profiler */
- gpu_dbg_cde = BIT(10), /* cde info messages */
- gpu_dbg_cde_ctx = BIT(11), /* cde context usage messages */
- gpu_dbg_ctxsw = BIT(12), /* ctxsw tracing */
- gpu_dbg_sched = BIT(13), /* sched control tracing */
- gpu_dbg_map_v = BIT(14), /* verbose mem mappings */
- gpu_dbg_sema = BIT(15), /* semaphore debugging */
- gpu_dbg_sema_v = BIT(16), /* verbose semaphore debugging */
- gpu_dbg_pmu_pstate = BIT(17), /* p state controlled by pmu */
- gpu_dbg_xv = BIT(18), /* XVE debugging */
- gpu_dbg_shutdown = BIT(19), /* GPU shutdown tracing */
- gpu_dbg_kmem = BIT(20), /* Kmem tracking debugging */
- gpu_dbg_mem = BIT(31), /* memory accesses, very verbose */
-};
-
/* operations that will need to be executed on non stall workqueue */
enum gk20a_nonstall_ops {
gk20a_nonstall_ops_wakeup_semaphore = BIT(0), /* wake up semaphore */
gk20a_nonstall_ops_post_events = BIT(1),
};
-extern u32 gk20a_dbg_mask;
-#ifdef CONFIG_GK20A_TRACE_PRINTK
-extern u32 gk20a_dbg_ftrace;
-#define gk20a_dbg(dbg_mask, format, arg...) \
-do { \
- if (unlikely((dbg_mask) & gk20a_dbg_mask)) { \
- if (gk20a_dbg_ftrace) \
- trace_printk(format "\n", ##arg); \
- else \
- pr_info("gk20a %s: " format "\n", \
- __func__, ##arg); \
- } \
-} while (0)
-#else
-#define gk20a_dbg(dbg_mask, format, arg...) \
-do { \
- if (unlikely((dbg_mask) & gk20a_dbg_mask)) { \
- pr_info("gk20a %s: " format "\n", \
- __func__, ##arg); \
- } \
-} while (0)
-#endif
-
-#define gk20a_err(d, fmt, arg...) \
- do { \
- if (d) \
- dev_err(d, "%s: " fmt "\n", __func__, ##arg); \
- } while (0)
-
-#define gk20a_warn(d, fmt, arg...) \
- do { \
- if (d) \
- dev_warn(d, "%s: " fmt "\n", __func__, ##arg); \
- } while (0)
-
-
-#define gk20a_dbg_fn(fmt, arg...) \
- gk20a_dbg(gpu_dbg_fn, fmt, ##arg)
-
-#define gk20a_dbg_info(fmt, arg...) \
- gk20a_dbg(gpu_dbg_info, fmt, ##arg)
-
void gk20a_init_clk_ops(struct gpu_ops *gops);
/* register accessors */
diff --git a/drivers/gpu/nvgpu/gp10b/cde_gp10b.c b/drivers/gpu/nvgpu/gp10b/cde_gp10b.c
index 567002118..5f68de5a7 100644
--- a/drivers/gpu/nvgpu/gp10b/cde_gp10b.c
+++ b/drivers/gpu/nvgpu/gp10b/cde_gp10b.c
@@ -129,9 +129,9 @@ static int gp10b_populate_scatter_buffer(struct gk20a *g,
if ((page & 7) != 0)
scatter_buffer[page >> 3] = d;
- if (unlikely(gpu_dbg_cde & gk20a_dbg_mask)) {
+ if (nvgpu_log_mask_enabled(g, gpu_dbg_cde)) {
gk20a_dbg(gpu_dbg_cde, "scatterBuffer content:");
- for (i=0; i < page>>3; i++) {
+ for (i = 0; i < page >> 3; i++) {
gk20a_dbg(gpu_dbg_cde, " %x", scatter_buffer[i]);
}
}
diff --git a/drivers/gpu/nvgpu/include/nvgpu/log.h b/drivers/gpu/nvgpu/include/nvgpu/log.h
new file mode 100644
index 000000000..267389936
--- /dev/null
+++ b/drivers/gpu/nvgpu/include/nvgpu/log.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __NVGPU_DEBUGGING_H__
+#define __NVGPU_DEBUGGING_H__
+
+struct gk20a;
+
+enum nvgpu_log_type {
+ ERROR,
+ WARNING,
+ DEBUG
+};
+
+/*
+ * Each OS must implement these functions. They handle the OS specific nuances
+ * of printing data to a UART, log, whatever.
+ */
+__attribute__((format (printf, 5, 6)))
+void __nvgpu_log_msg(struct gk20a *g, const char *func_name, int line,
+ enum nvgpu_log_type type, const char *fmt, ...);
+
+__attribute__((format (printf, 5, 6)))
+void __nvgpu_log_dbg(struct gk20a *g, u32 log_mask,
+ const char *func_name, int line,
+ const char *fmt, ...);
+
+/*
+ * Use this define to set a default mask.
+ */
+#define NVGPU_DEFAULT_DBG_MASK (0)
+
+enum nvgpu_log_categories {
+ gpu_dbg_info = BIT(0), /* Lightly verbose info. */
+ gpu_dbg_fn = BIT(1), /* Function name tracing. */
+ gpu_dbg_reg = BIT(2), /* Register accesses; very verbose. */
+ gpu_dbg_pte = BIT(3), /* GMMU PTEs. */
+ gpu_dbg_intr = BIT(4), /* Interrupts. */
+ gpu_dbg_pmu = BIT(5), /* gk20a pmu. */
+ gpu_dbg_clk = BIT(6), /* gk20a clk. */
+ gpu_dbg_map = BIT(7), /* Memory mappings. */
+ gpu_dbg_map_v = BIT(8), /* Verbose mem mappings. */
+ gpu_dbg_gpu_dbg = BIT(9), /* GPU debugger/profiler. */
+ gpu_dbg_cde = BIT(10), /* cde info messages. */
+ gpu_dbg_cde_ctx = BIT(11), /* cde context usage messages. */
+ gpu_dbg_ctxsw = BIT(12), /* ctxsw tracing. */
+ gpu_dbg_sched = BIT(13), /* Sched control tracing. */
+ gpu_dbg_sema = BIT(14), /* Semaphore debugging. */
+ gpu_dbg_sema_v = BIT(15), /* Verbose semaphore debugging. */
+ gpu_dbg_pmu_pstate = BIT(16), /* p state controlled by pmu. */
+ gpu_dbg_xv = BIT(17), /* XVE debugging. */
+ gpu_dbg_shutdown = BIT(18), /* GPU shutdown tracing. */
+ gpu_dbg_kmem = BIT(19), /* Kmem tracking debugging. */
+ gpu_dbg_mem = BIT(31), /* memory accesses; very verbose. */
+};
+
+/**
+ * nvgpu_log_mask_enabled - Check if logging is enabled
+ *
+ * @g - The GPU.
+ * @log_mask - The mask the check against.
+ *
+ * Check if, given the passed mask, logging would actually happen. This is
+ * useful for avoiding calling the logging function many times when we know that
+ * said prints would not happen. For example for-loops of log statements in
+ * critical paths.
+ */
+int nvgpu_log_mask_enabled(struct gk20a *g, u32 log_mask);
+
+/**
+ * nvgpu_log - Print a debug message
+ *
+ * @g - The GPU.
+ * @log_mask - A mask defining when the print should happen. See enum
+ * %nvgpu_log_categories.
+ * @fmt - A format string (printf style).
+ * @arg... - Arguments for the format string.
+ *
+ * Print a message if the log_mask matches the enabled debugging.
+ */
+#define nvgpu_log(g, log_mask, fmt, arg...) \
+ __nvgpu_log_dbg(g, log_mask, __func__, __LINE__, fmt, ##arg); \
+
+/**
+ * nvgpu_err - Print an error
+ *
+ * @g - The GPU.
+ * @fmt - A format string (printf style).
+ * @arg... - Arguments for the format string.
+ *
+ * Uncondtionally print an error message.
+ */
+#define nvgpu_err(g, fmt, arg...) \
+ __nvgpu_log_msg(g, __func__, __LINE__, ERROR, fmt, ##arg)
+
+/**
+ * nvgpu_err - Print a warning
+ *
+ * @g - The GPU.
+ * @fmt - A format string (printf style).
+ * @arg... - Arguments for the format string.
+ *
+ * Uncondtionally print a warming message.
+ */
+#define nvgpu_warn(g, fmt, arg...) \
+ __nvgpu_log_msg(g, __func__, __LINE__, WARNING, fmt, ##arg)
+
+/*
+ * Some convenience macros.
+ */
+#define nvgpu_log_fn(g, fmt, arg...) nvgpu_log(g, gpu_dbg_fn, fmt, ##arg)
+#define nvgpu_log_info(g, fmt, arg...) nvgpu_log(g, gpu_dbg_info, fmt, ##arg)
+
+/******************************************************************************
+ * The old legacy debugging API minus some parts that are unnecessary. *
+ * Please, please, please do not use this!!! This is still around to aid *
+ * transitioning to the new API. *
+ * *
+ * This changes up the print formats to be closer to the new APIs formats. *
+ * Also it removes the dev_warn() and dev_err() usage. Those arguments are *
+ * ignored now. *
+ ******************************************************************************/
+
+/*
+ * This exist for backwards compatibility with the old debug/logging API. If you
+ * want ftrace support use the new API!
+ */
+extern u32 nvgpu_dbg_mask;
+
+#define gk20a_dbg(log_mask, fmt, arg...) \
+ do { \
+ if (((log_mask) & nvgpu_dbg_mask) != 0) \
+ __nvgpu_log_msg(NULL, __func__, __LINE__, \
+ DEBUG, fmt "\n", ##arg); \
+ } while (0)
+
+#define gk20a_err(d, fmt, arg...) \
+ do { \
+ __nvgpu_log_msg(NULL, __func__, __LINE__, ERROR, \
+ fmt "\n", ##arg); \
+ (void)(d); \
+ } while (0)
+
+#define gk20a_warn(d, fmt, arg...) \
+ do { \
+ __nvgpu_log_msg(NULL, __func__, __LINE__, WARNING, \
+ fmt "\n", ##arg); \
+ (void)(d); \
+ } while (0)
+
+/*
+ * Some convenience macros.
+ */
+#define gk20a_dbg_fn(fmt, arg...) gk20a_dbg(gpu_dbg_fn, fmt, ##arg)
+#define gk20a_dbg_info(fmt, arg...) gk20a_dbg(gpu_dbg_info, fmt, ##arg)
+
+#endif
diff --git a/drivers/gpu/nvgpu/include/nvgpu/semaphore.h b/drivers/gpu/nvgpu/include/nvgpu/semaphore.h
index 6c9b81182..ade48178d 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/semaphore.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/semaphore.h
@@ -18,6 +18,7 @@
#include
#include
+#include
#include
#include "gk20a/gk20a.h"