blob: b789252cd015b5a7f4fe2e795d2fe7ba1fcf7689 [file] [log] [blame]
/*
* include/scst_debug.h
*
* Copyright (C) 2004 - 2018 Vladislav Bolkhovitin <vst@vlnb.net>
* Copyright (C) 2004 - 2005 Leonid Stoljar
* Copyright (C) 2007 - 2018 Western Digital Corporation
*
* Contains macros for execution tracing and error reporting
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2
* of the License.
*
* 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.
*/
#ifndef __SCST_DEBUG_H
#define __SCST_DEBUG_H
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
#include <linux/autoconf.h> /* for CONFIG_* */
#else
#include <generated/autoconf.h> /* for CONFIG_* */
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19)
#include <linux/bug.h> /* for WARN_ON_ONCE */
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27)
#include <linux/ratelimit.h>
#endif
#ifdef INSIDE_KERNEL_TREE
#include <scst/backport.h>
#else
#include <build_mode.h>
#include <backport.h>
#endif
#if !defined(INSIDE_KERNEL_TREE)
#ifdef CONFIG_SCST_DEBUG
#ifdef __CHECKER__
/*
* Avoid that the while (...) local_bh_enable() loop confuses the lock checking
* code in smatch.
*/
#define sBUG() BUG()
#define sBUG_ON(p) BUG_ON((p))
#else
#define sBUG() do { \
pr_crit("BUG at %s:%d\n", __FILE__, __LINE__); \
local_irq_enable(); \
while (in_softirq()) \
local_bh_enable(); \
BUG(); \
} while (0)
#define sBUG_ON(p) do { \
if (unlikely(p)) { \
pr_crit("BUG at %s:%d (%s)\n", \
__FILE__, __LINE__, #p); \
local_irq_enable(); \
while (in_softirq()) \
local_bh_enable(); \
BUG(); \
} \
} while (0)
#endif
#else
#define sBUG() BUG()
#define sBUG_ON(p) BUG_ON(p)
#endif
#endif
#if defined(CONFIG_SCST_EXTRACHECKS) || defined(__COVERITY__)
#define EXTRACHECKS_BUG() sBUG()
#define EXTRACHECKS_BUG_ON(a) sBUG_ON(a)
#define EXTRACHECKS_WARN_ON(a) WARN_ON(a)
#define EXTRACHECKS_WARN_ON_ONCE(a) WARN_ON_ONCE(a)
#else
#define EXTRACHECKS_BUG() do { } while (0)
#define EXTRACHECKS_BUG_ON(a) do { } while (0)
#define EXTRACHECKS_WARN_ON(a) do { } while (0)
#define EXTRACHECKS_WARN_ON_ONCE(a) do { } while (0)
#endif
#define TRACE_NULL 0x00000000
#define TRACE_DEBUG 0x00000001
#define TRACE_FUNCTION 0x00000002
#define TRACE_LINE 0x00000004
#define TRACE_PID 0x00000008
#ifndef GENERATING_UPSTREAM_PATCH
#define TRACE_ENTRYEXIT 0x00000010
#endif
#define TRACE_BUFF 0x00000020
#define TRACE_MEMORY 0x00000040
#define TRACE_SG_OP 0x00000080
#define TRACE_OUT_OF_MEM 0x00000100
#define TRACE_MINOR 0x00000200 /* less important events */
#define TRACE_MGMT 0x00000400
#define TRACE_MGMT_DEBUG 0x00000800
#define TRACE_SCSI 0x00001000
#define TRACE_SPECIAL 0x00002000 /* filtering debug, etc */
#define TRACE_FLOW_CONTROL 0x00004000 /* flow control in action */
#define TRACE_PRES 0x00008000
#define TRACE_BLOCKING 0x00010000
#define TRACE_ALL 0xffffffff
/* Flags 0xXXXXXXXXXX000000 are local for users */
#define TRACE_MINOR_AND_MGMT_DBG (TRACE_MINOR|TRACE_MGMT_DEBUG)
/*
* Note: in the next two printk() statements the KERN_CONT macro is only
* present to suppress a checkpatch warning (KERN_CONT is defined as "").
*/
#define PRINT(log_flag, format, args...) \
printk(log_flag format "\n", ## args)
#define PRINTN(log_flag, format, args...) \
printk(log_flag format, ## args)
#ifdef LOG_PREFIX
#define __LOG_PREFIX LOG_PREFIX
#else
#define __LOG_PREFIX NULL
#endif
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
#ifndef CONFIG_SCST_DEBUG
#define ___unlikely(a) (a)
#else
#define ___unlikely(a) unlikely(a)
#endif
int __printf(6, 7)
debug_print_with_prefix(unsigned long trace_flag,
const char *severity, const char *prefix, const char *func, int line,
const char *fmt, ...);
void debug_print_buffer(const void *data, int len);
const char *debug_transport_id_to_initiator_name(const uint8_t *transport_id);
#define TRACING_MINOR() (trace_flag & TRACE_MINOR)
#define TRACE(trace, format, args...) \
do { \
if (___unlikely(trace_flag & (trace))) { \
debug_print_with_prefix(trace_flag, KERN_INFO, \
__LOG_PREFIX, __func__, __LINE__, format, ## args); \
} \
} while (0)
#define TRACE_PR(format, args...) TRACE(TRACE_PRES, format, ## args)
#ifdef CONFIG_SCST_DEBUG
#define PRINT_BUFFER(message, buff, len) \
do { \
PRINT(KERN_INFO, "%s:%s:", __func__, message); \
debug_print_buffer(buff, len); \
} while (0)
#else
#define PRINT_BUFFER(message, buff, len) \
do { \
PRINT(KERN_INFO, "%s:", message); \
debug_print_buffer(buff, len); \
} while (0)
#endif
#define PRINT_BUFF_FLAG(flag, message, buff, len) \
do { \
if (___unlikely(trace_flag & (flag))) { \
debug_print_with_prefix(trace_flag, KERN_INFO, NULL, \
__func__, __LINE__, "%s:", message); \
debug_print_buffer(buff, len); \
} \
} while (0)
#define PRINT_LOG_FLAG(log_flag, format, args...) \
debug_print_with_prefix(trace_flag, KERN_INFO, __LOG_PREFIX, \
__func__, __LINE__, format, ## args)
#define PRINT_WARNING(format, args...) \
debug_print_with_prefix(trace_flag, KERN_WARNING, __LOG_PREFIX, \
__func__, __LINE__, "***WARNING***: " format, ## args)
#define PRINT_ERROR(format, args...) \
debug_print_with_prefix(trace_flag, KERN_ERR, __LOG_PREFIX, \
__func__, __LINE__, "***ERROR***: " format, ## args)
#define PRINT_CRIT_ERROR(format, args...) \
debug_print_with_prefix(trace_flag, KERN_CRIT, __LOG_PREFIX, \
__func__, __LINE__, "***CRITICAL ERROR***: " format, ## args)
#define PRINT_INFO(format, args...) \
debug_print_with_prefix(trace_flag, KERN_INFO, __LOG_PREFIX, \
__func__, __LINE__, format, ## args)
#else /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */
#define TRACING_MINOR() (false)
#define TRACE(trace, format, args...) \
do { (void)(trace); no_printk(format, ##args); } while (0)
#define PRINT_BUFFER(message, buff, len) \
((void)(message), (void)(buff), (void)(len))
#define PRINT_BUFF_FLAG(flag, message, buff, len) \
((void)(flag), (void)(message), (void)(buff), (void)(len))
/*
* no_printk still calls its arguments, so we can not use it in perf build
* for TRACE_PR or debug_transport_id_to_initiator_name() is not going to
* be found.
*/
#define TRACE_PR(format, args...) do { } while (0)
#ifdef LOG_PREFIX
#define PRINT_INFO(format, args...) \
PRINT(KERN_INFO, "%s: " format, LOG_PREFIX, ## args)
#define PRINT_WARNING(format, args...) \
PRINT(KERN_WARNING, "%s: ***WARNING***: " format, LOG_PREFIX, ## args)
#define PRINT_ERROR(format, args...) \
PRINT(KERN_ERR, "%s: ***ERROR***: " format, LOG_PREFIX, ## args)
#define PRINT_CRIT_ERROR(format, args...) \
PRINT(KERN_CRIT, "%s: ***CRITICAL ERROR***: " \
format, LOG_PREFIX, ## args)
#else /* LOG_PREFIX */
#define PRINT_INFO(format, args...) \
PRINT(KERN_INFO, format, ## args)
#define PRINT_WARNING(format, args...) \
PRINT(KERN_WARNING, "***WARNING***: " format, ## args)
#define PRINT_ERROR(format, args...) \
PRINT(KERN_ERR, "***ERROR***: " format, ## args)
#define PRINT_CRIT_ERROR(format, args...) \
PRINT(KERN_CRIT, "***CRITICAL ERROR***: " format, ## args)
#endif /* LOG_PREFIX */
#endif /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */
#define PRINT_ERROR_RATELIMITED(format, args...) \
do { \
static DEFINE_RATELIMIT_STATE(_rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
\
if (__ratelimit(&_rs)) \
PRINT_ERROR(format, ##args); \
} while (0)
#ifdef CONFIG_SCST_DEBUG
#define TRACE_DBG_FLAG(trace, format, args...) \
do { \
if (trace_flag & (trace)) { \
debug_print_with_prefix(trace_flag, KERN_INFO, NULL, \
__func__, __LINE__, format, ## args); \
} \
} while (0)
#define TRACE_MEM(format, args...) \
TRACE_DBG_FLAG(TRACE_MEMORY, format, ## args)
#define TRACE_SG(format, args...) \
TRACE_DBG_FLAG(TRACE_SG_OP, format, ## args)
#define TRACE_DBG(format, args...) \
TRACE_DBG_FLAG(TRACE_DEBUG, format, ## args)
#define TRACE_DBG_SPECIAL(format, args...) \
TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_SPECIAL, format, ## args)
#define TRACE_MGMT_DBG(format, args...) \
TRACE_DBG_FLAG(TRACE_MGMT_DEBUG, format, ## args)
#define TRACE_MGMT_DBG_SPECIAL(args...) \
TRACE_DBG_FLAG(TRACE_MGMT_DEBUG|TRACE_SPECIAL, format, ## args)
#define TRACE_BLOCK(format, args...) \
TRACE_DBG_FLAG(TRACE_BLOCKING, format, ## args)
#define TRACE_BUFFER(message, buff, len) \
do { \
if (trace_flag & TRACE_BUFF) { \
debug_print_with_prefix(trace_flag, KERN_INFO, NULL, \
__func__, __LINE__, "%s:", message); \
debug_print_buffer(buff, len); \
} \
} while (0)
#define TRACE_BUFF_FLAG(flag, message, buff, len) \
do { \
if (trace_flag & (flag)) { \
debug_print_with_prefix(trace_flag, KERN_INFO, NULL, \
__func__, __LINE__, "%s:", message); \
debug_print_buffer(buff, len); \
} \
} while (0)
#ifndef GENERATING_UPSTREAM_PATCH
#define TRACE_ENTRY() \
do { \
if (trace_flag & TRACE_ENTRYEXIT) { \
if (trace_flag & TRACE_PID) { \
PRINT(KERN_INFO, "[%d]: ENTRY %s", current->pid, \
__func__); \
} \
else { \
PRINT(KERN_INFO, "ENTRY %s", __func__); \
} \
} \
} while (0)
#define TRACE_EXIT() \
do { \
if (trace_flag & TRACE_ENTRYEXIT) { \
if (trace_flag & TRACE_PID) { \
PRINT(KERN_INFO, "[%d]: EXIT %s", current->pid, \
__func__); \
} \
else { \
PRINT(KERN_INFO, "EXIT %s", __func__); \
} \
} \
} while (0)
#define TRACE_EXIT_RES(res) \
do { \
unsigned long lres = res; \
\
if (trace_flag & TRACE_ENTRYEXIT) { \
if (trace_flag & TRACE_PID) { \
PRINT(KERN_INFO, "[%d]: EXIT %s: %ld", current->pid, \
__func__, lres); \
} else { \
PRINT(KERN_INFO, "EXIT %s: %ld", \
__func__, lres); \
} \
} \
} while (0)
#define TRACE_EXIT_HRES(res) \
do { \
unsigned long lres = (unsigned long)(res); \
\
if (trace_flag & TRACE_ENTRYEXIT) { \
if (trace_flag & TRACE_PID) { \
PRINT(KERN_INFO, "[%d]: EXIT %s: 0x%lx", current->pid, \
__func__, lres); \
} else { \
PRINT(KERN_INFO, "EXIT %s: %lx", \
__func__, lres); \
} \
} \
} while (0)
#endif
#else /* CONFIG_SCST_DEBUG */
#define TRACE_MEM(format, args...) no_printk(format, ##args)
#define TRACE_SG(format, args...) no_printk(format, ##args)
#define TRACE_DBG(format, args...) no_printk(format, ##args)
#define TRACE_DBG_FLAG(flag, format, args...) \
do { (void)(flag); no_printk(format, ##args); } while (0)
#define TRACE_DBG_SPECIAL(format, args...) no_printk(format, ##args)
#define TRACE_MGMT_DBG(format, args...) no_printk(format, ##args)
#define TRACE_MGMT_DBG_SPECIAL(format, args...) no_printk(format, ##args)
#define TRACE_BLOCK(format, args...) no_printk(format, ##args)
#define TRACE_BUFFER(message, buff, len) \
((void)(message), (void)(buff), (void)(len))
#define TRACE_BUFF_FLAG(flag, message, buff, len) \
((void)(flag), (void)(message), (void)(buff), (void)(len))
#ifndef GENERATING_UPSTREAM_PATCH
#define TRACE_ENTRY() do {} while (0)
#define TRACE_EXIT() do {} while (0)
#define TRACE_EXIT_RES(res) do {} while (0)
#define TRACE_EXIT_HRES(res) do {} while (0)
#endif
#endif /* CONFIG_SCST_DEBUG */
#if defined(CONFIG_SCST_DEBUG) && defined(CONFIG_DEBUG_SLAB)
#define SCST_SLAB_FLAGS (SLAB_RED_ZONE | SLAB_POISON)
#else
#define SCST_SLAB_FLAGS 0L
#endif
#define PRINT_WARNING_ONCE(format, args...) \
do { \
static bool __warned; \
if (!__warned) { \
__warned = true; \
PRINT_WARNING(format, ## args); \
} \
} while (0)
#endif /* __SCST_DEBUG_H */