From e3bd4ae2a59fef37a85fbca168fc479dd5514023 Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Mon, 27 Mar 2017 10:41:53 -0700 Subject: gpu: nvgpu: debugging API update Update the debugging APIs in nvgpu to be more coherent and less dependent on Linux kernel APIs and data structures. The old API is maintained for backwards compatibility but the prints themselves are changed. The old API now prints stuff like this: [ 46.376077] nvgpu: gk20a_channel_suspend:3430 [DBG] suspend channel 508 [ 46.376242] nvgpu: gk20a_channel_suspend:3430 [DBG] suspend channel 509 [ 46.376359] nvgpu: gk20a_channel_suspend:3430 [DBG] suspend channel 510 [ 46.376466] nvgpu: gk20a_channel_suspend:3430 [DBG] suspend channel 511 [ 46.376604] nvgpu: gk20a_fifo_update_runlist_locked:3090 [DBG] runlist_id : 0, switch to new buffer 0x 4003a0000 [ 46.378348] nvgpu: gk20a_mm_l2_flush:5259 [DBG] l2_flush_dirty 0x2 [ 46.378562] nvgpu: clk_config_pll:170 [DBG] low_PL 1(div1), high_PL 2(div2) [ 46.378684] nvgpu: clk_config_pll:170 [DBG] low_PL 8(div8), high_PL 17(div17) Each line starts with 'nvgpu:' since this is the nvgpu driver. Then there's the function name which is is right justified and post-fixed with a line number. This keeps all statements lined up so long as the function name does not exceed the length of characters alloted for function names (33 currently). Lines are also left justified with 4 available spaces since there are currently no source files with over 9999 lines. The type of message (DBG, WRN, ERR) is then printed in brackets. Finally there's whatever message is to be printed. The new API will be largely the same except there will be an additional print of the GPU that the message has originated from in order to help debug cases where both an iGPU and dGPU are active. Also the implicit newline added in the legacy API has been removed. This is inline with essentially every other print function in the C world. There are numerous places where '\n' is added despite it not being needed which results in log files being littered with blank lines. This makes the logs much harder to read. Bug ... Change-Id: I7bc87f2dbbaebf6eb6c9de1a629a0e2963e1804c Signed-off-by: Alex Waterman Reviewed-on: http://git-master/r/1329487 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile.nvgpu | 1 + drivers/gpu/nvgpu/common/linux/log.c | 130 +++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/debug_gk20a.c | 17 +-- drivers/gpu/nvgpu/gk20a/gk20a.c | 5 - drivers/gpu/nvgpu/gk20a/gk20a.h | 83 +------------- drivers/gpu/nvgpu/gp10b/cde_gp10b.c | 4 +- drivers/gpu/nvgpu/include/nvgpu/log.h | 170 ++++++++++++++++++++++++++++ drivers/gpu/nvgpu/include/nvgpu/semaphore.h | 1 + 8 files changed, 318 insertions(+), 93 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/linux/log.c create mode 100644 drivers/gpu/nvgpu/include/nvgpu/log.h (limited to 'drivers/gpu/nvgpu') diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu index 8a608ca4..b8a3f033 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 00000000..9dd965ec --- /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 b666bb16..a8b9c5fb 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 6d80f3ba..c8acf6f7 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 ec27ed77..2a9f8a06 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 56700211..5f68de5a 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 00000000..26738993 --- /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 6c9b8118..ade48178 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" -- cgit v1.2.2