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"