Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *   S/390 debug facility
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *    Copyright IBM Corp. 1999, 2020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *    Author(s): Michael Holzheu (holzheu@de.ibm.com),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *		 Holger Smolinski (Holger.Smolinski@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *    Bugreports to: <Linux390@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #define KMSG_COMPONENT "s390dbf"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/minmax.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #define DEBUG_PROLOG_ENTRY -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #define ALL_AREAS 0 /* copy all debug areas */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #define NO_AREAS  1 /* copy no debug areas */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) /* typedefs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) typedef struct file_private_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 	loff_t offset;			/* offset of last read in file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 	int    act_area;		/* number of last formated area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 	int    act_page;		/* act page in given area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 	int    act_entry;		/* last formated entry (offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 					/* relative to beginning of last */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 					/* formated page) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 	size_t act_entry_offset;	/* up to this offset we copied */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 					/* in last read the last formated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 					/* entry to userland */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 	char   temp_buf[2048];		/* buffer for output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	debug_info_t *debug_info_org;	/* original debug information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 	debug_info_t *debug_info_snap;	/* snapshot of debug information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	struct debug_view *view;	/* used view of debug info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) } file_private_info_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) typedef struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	char *string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 	 * This assumes that all args are converted into longs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	 * on L/390 this is the case for all types of parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 	 * except of floats, and long long (32 bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	long args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) } debug_sprintf_entry_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) /* internal function prototyes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) static int debug_init(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) static ssize_t debug_output(struct file *file, char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 			    size_t user_len, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) static ssize_t debug_input(struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 			   size_t user_len, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) static int debug_open(struct inode *inode, struct file *file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) static int debug_close(struct inode *inode, struct file *file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) static debug_info_t *debug_info_create(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 				       int nr_areas, int buf_size, umode_t mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) static void debug_info_get(debug_info_t *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) static void debug_info_put(debug_info_t *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) static int debug_prolog_level_fn(debug_info_t *id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 				 struct debug_view *view, char *out_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) static int debug_input_level_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 				struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 				size_t user_buf_size, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) static int debug_prolog_pages_fn(debug_info_t *id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 				 struct debug_view *view, char *out_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) static int debug_input_pages_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 				struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 				size_t user_buf_size, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 				struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 				size_t user_buf_size, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 				     char *out_buf, const char *in_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 				   char *out_buf, debug_sprintf_entry_t *curr_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) static void debug_areas_swap(debug_info_t *a, debug_info_t *b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) static void debug_events_append(debug_info_t *dest, debug_info_t *src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) /* globals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) struct debug_view debug_hex_ascii_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 	"hex_ascii",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	&debug_dflt_header_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	&debug_hex_ascii_format_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) EXPORT_SYMBOL(debug_hex_ascii_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) static struct debug_view debug_level_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	"level",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	&debug_prolog_level_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	&debug_input_level_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) static struct debug_view debug_pages_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	"pages",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	&debug_prolog_pages_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	&debug_input_pages_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) static struct debug_view debug_flush_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	"flush",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	&debug_input_flush_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) struct debug_view debug_sprintf_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	"sprintf",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	&debug_dflt_header_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	(debug_format_proc_t *)&debug_sprintf_format_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) EXPORT_SYMBOL(debug_sprintf_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) /* used by dump analysis tools to determine version of debug feature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) static unsigned int __used debug_feature_version = __DEBUG_FEATURE_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) /* static globals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) static debug_info_t *debug_area_first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) static debug_info_t *debug_area_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) static DEFINE_MUTEX(debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) static int initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) static int debug_critical;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) static const struct file_operations debug_file_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	.owner	 = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	.read	 = debug_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	.write	 = debug_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	.open	 = debug_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	.release = debug_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	.llseek  = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) static struct dentry *debug_debugfs_root_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) /* functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174)  * debug_areas_alloc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175)  * - Debug areas are implemented as a threedimensonal array:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176)  *   areas[areanumber][pagenumber][pageoffset]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) static debug_entry_t ***debug_areas_alloc(int pages_per_area, int nr_areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	debug_entry_t ***areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	areas = kmalloc_array(nr_areas, sizeof(debug_entry_t **), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	if (!areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 		goto fail_malloc_areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	for (i = 0; i < nr_areas; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 		/* GFP_NOWARN to avoid user triggerable WARN, we handle fails */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 		areas[i] = kmalloc_array(pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 					 sizeof(debug_entry_t *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 					 GFP_KERNEL | __GFP_NOWARN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 		if (!areas[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 			goto fail_malloc_areas2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 		for (j = 0; j < pages_per_area; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 			areas[i][j] = kzalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 			if (!areas[i][j]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 				for (j--; j >= 0 ; j--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 					kfree(areas[i][j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 				kfree(areas[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 				goto fail_malloc_areas2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	return areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) fail_malloc_areas2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	for (i--; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		for (j = 0; j < pages_per_area; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 			kfree(areas[i][j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 		kfree(areas[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	kfree(areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) fail_malloc_areas:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218)  * debug_info_alloc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219)  * - alloc new debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) static debug_info_t *debug_info_alloc(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 				      int nr_areas, int buf_size, int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 				      int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	debug_info_t *rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	/* alloc everything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	rc = kmalloc(sizeof(debug_info_t), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 		goto fail_malloc_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	rc->active_entries = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	if (!rc->active_entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 		goto fail_malloc_active_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	rc->active_pages = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	if (!rc->active_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 		goto fail_malloc_active_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	if ((mode == ALL_AREAS) && (pages_per_area != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 		rc->areas = debug_areas_alloc(pages_per_area, nr_areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 		if (!rc->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 			goto fail_malloc_areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 		rc->areas = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	/* initialize members */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	spin_lock_init(&rc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	rc->pages_per_area = pages_per_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	rc->nr_areas	   = nr_areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	rc->active_area    = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	rc->level	   = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	rc->buf_size	   = buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	rc->entry_size	   = sizeof(debug_entry_t) + buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	strlcpy(rc->name, name, sizeof(rc->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 	memset(rc->debugfs_entries, 0, DEBUG_MAX_VIEWS * sizeof(struct dentry *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	refcount_set(&(rc->ref_count), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) fail_malloc_areas:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	kfree(rc->active_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) fail_malloc_active_pages:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	kfree(rc->active_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) fail_malloc_active_entries:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	kfree(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) fail_malloc_rc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271)  * debug_areas_free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272)  * - free all debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) static void debug_areas_free(debug_info_t *db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	if (!db_info->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	for (i = 0; i < db_info->nr_areas; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 		for (j = 0; j < db_info->pages_per_area; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 			kfree(db_info->areas[i][j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 		kfree(db_info->areas[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	kfree(db_info->areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	db_info->areas = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290)  * debug_info_free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291)  * - free memory debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) static void debug_info_free(debug_info_t *db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	debug_areas_free(db_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	kfree(db_info->active_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	kfree(db_info->active_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	kfree(db_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302)  * debug_info_create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303)  * - create new debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) static debug_info_t *debug_info_create(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 				       int nr_areas, int buf_size, umode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	debug_info_t *rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	rc = debug_info_alloc(name, pages_per_area, nr_areas, buf_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 			      DEBUG_DEFAULT_LEVEL, ALL_AREAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	rc->mode = mode & ~S_IFMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	refcount_set(&rc->ref_count, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323)  * debug_info_copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324)  * - copy debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) static debug_info_t *debug_info_copy(debug_info_t *in, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	debug_info_t *rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	/* get a consistent copy of the debug areas */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 		rc = debug_info_alloc(in->name, in->pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 			in->nr_areas, in->buf_size, in->level, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 		spin_lock_irqsave(&in->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 		if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 		/* has something changed in the meantime ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		if ((rc->pages_per_area == in->pages_per_area) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 		    (rc->nr_areas == in->nr_areas)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 		spin_unlock_irqrestore(&in->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 		debug_info_free(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	} while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	if (mode == NO_AREAS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	for (i = 0; i < in->nr_areas; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 		for (j = 0; j < in->pages_per_area; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 			memcpy(rc->areas[i][j], in->areas[i][j], PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	spin_unlock_irqrestore(&in->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361)  * debug_info_get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362)  * - increments reference count for debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) static void debug_info_get(debug_info_t *db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	if (db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 		refcount_inc(&db_info->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371)  * debug_info_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372)  * - decreases reference count for debug-info and frees it if necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) static void debug_info_put(debug_info_t *db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	if (!db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	if (refcount_dec_and_test(&db_info->ref_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		debug_info_free(db_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383)  * debug_format_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384)  * - format one debug entry and return size of formated data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) static int debug_format_entry(file_private_info_t *p_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	debug_info_t *id_snap	= p_info->debug_info_snap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	struct debug_view *view = p_info->view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	debug_entry_t *act_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	size_t len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	if (p_info->act_entry == DEBUG_PROLOG_ENTRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 		/* print prolog */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 		if (view->prolog_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 			len += view->prolog_proc(id_snap, view, p_info->temp_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	if (!id_snap->areas) /* this is true, if we have a prolog only view */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 		goto out;    /* or if 'pages_per_area' is 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	act_entry = (debug_entry_t *) ((char *)id_snap->areas[p_info->act_area]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 				       [p_info->act_page] + p_info->act_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	if (act_entry->clock == 0LL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 		goto out; /* empty entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	if (view->header_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 		len += view->header_proc(id_snap, view, p_info->act_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 					 act_entry, p_info->temp_buf + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	if (view->format_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		len += view->format_proc(id_snap, view, p_info->temp_buf + len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 					 DEBUG_DATA(act_entry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417)  * debug_next_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418)  * - goto next entry in p_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) static inline int debug_next_entry(file_private_info_t *p_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	debug_info_t *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	id = p_info->debug_info_snap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	if (p_info->act_entry == DEBUG_PROLOG_ENTRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 		p_info->act_entry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 		p_info->act_page  = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	if (!id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	p_info->act_entry += id->entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	/* switch to next page, if we reached the end of the page  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	if (p_info->act_entry > (PAGE_SIZE - id->entry_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 		/* next page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		p_info->act_entry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 		p_info->act_page += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 		if ((p_info->act_page % id->pages_per_area) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 			/* next area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 			p_info->act_area++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 			p_info->act_page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		if (p_info->act_area >= id->nr_areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451)  * debug_output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452)  * - called for user read()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453)  * - copies formated debug entries to the user buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) static ssize_t debug_output(struct file *file,		/* file descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 			    char __user *user_buf,	/* user buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 			    size_t len,			/* length of buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 			    loff_t *offset)		/* offset in the file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	size_t count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	size_t entry_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	file_private_info_t *p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	p_info = (file_private_info_t *) file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	if (*offset != p_info->offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		return -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	if (p_info->act_area >= p_info->debug_info_snap->nr_areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	entry_offset = p_info->act_entry_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	while (count < len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 		int formatted_line_residue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		int formatted_line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 		int user_buf_residue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 		size_t copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		formatted_line_size = debug_format_entry(p_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		formatted_line_residue = formatted_line_size - entry_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		user_buf_residue = len-count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		copy_size = min(user_buf_residue, formatted_line_residue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		if (copy_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 			if (copy_to_user(user_buf + count, p_info->temp_buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 					 + entry_offset, copy_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 			count += copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 			entry_offset += copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		if (copy_size == formatted_line_residue) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 			entry_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 			if (debug_next_entry(p_info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	p_info->offset		 = *offset + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	p_info->act_entry_offset = entry_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	*offset = p_info->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)  * debug_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502)  * - called for user write()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503)  * - calls input function of view
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) static ssize_t debug_input(struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 			   size_t length, loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	file_private_info_t *p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	p_info = ((file_private_info_t *) file->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	if (p_info->view->input_proc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 		rc = p_info->view->input_proc(p_info->debug_info_org,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 					      p_info->view, file, user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 					      length, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	return rc; /* number of input characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525)  * debug_open:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526)  * - called for user open()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527)  * - copies formated output to private_data area of the file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528)  *   handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) static int debug_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	debug_info_t *debug_info, *debug_info_snapshot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	file_private_info_t *p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	debug_info = file_inode(file)->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	/* find debug view */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 		if (!debug_info->views[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		else if (debug_info->debugfs_entries[i] == file->f_path.dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 			goto found; /* found view ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	/* no entry found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	/* Make snapshot of current debug areas to get it consistent.	  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	/* To copy all the areas is only needed, if we have a view which  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	/* formats the debug areas. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	if (!debug_info->views[i]->format_proc && !debug_info->views[i]->header_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 		debug_info_snapshot = debug_info_copy(debug_info, NO_AREAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 		debug_info_snapshot = debug_info_copy(debug_info, ALL_AREAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	if (!debug_info_snapshot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 		rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	p_info = kmalloc(sizeof(file_private_info_t), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	if (!p_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		debug_info_free(debug_info_snapshot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 		rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	p_info->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	p_info->debug_info_snap = debug_info_snapshot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	p_info->debug_info_org	= debug_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	p_info->view = debug_info->views[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	p_info->act_area = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	p_info->act_page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	p_info->act_entry = DEBUG_PROLOG_ENTRY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	p_info->act_entry_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	file->private_data = p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	debug_info_get(debug_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	nonseekable_open(inode, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587)  * debug_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588)  * - called for user close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589)  * - deletes  private_data area of the file handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) static int debug_close(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	file_private_info_t *p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	p_info = (file_private_info_t *) file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	if (p_info->debug_info_snap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		debug_info_free(p_info->debug_info_snap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 	debug_info_put(p_info->debug_info_org);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	kfree(file->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 	return 0; /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) /* Create debugfs entries and add to internal list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) static void _debug_register(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	/* create root directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	id->debugfs_root_entry = debugfs_create_dir(id->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 						    debug_debugfs_root_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	/* append new element to linked list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	if (!debug_area_first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		/* first element in list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		debug_area_first = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 		id->prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 		/* append element to end of list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		debug_area_last->next = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 		id->prev = debug_area_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	debug_area_last = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	id->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	debug_register_view(id, &debug_level_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	debug_register_view(id, &debug_flush_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	debug_register_view(id, &debug_pages_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629)  * debug_register_mode() - creates and initializes debug area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631)  * @name:	Name of debug log (e.g. used for debugfs entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632)  * @pages_per_area:	Number of pages, which will be allocated per area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633)  * @nr_areas:	Number of debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634)  * @buf_size:	Size of data area in each debug entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635)  * @mode:	File mode for debugfs files. E.g. S_IRWXUGO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636)  * @uid:	User ID for debugfs files. Currently only 0 is supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637)  * @gid:	Group ID for debugfs files. Currently only 0 is supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640)  * - Handle for generated debug area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641)  * - %NULL if register failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643)  * Allocates memory for a debug log.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644)  * Must not be called within an interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) debug_info_t *debug_register_mode(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 				  int nr_areas, int buf_size, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 				  uid_t uid, gid_t gid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	debug_info_t *rc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	/* Since debugfs currently does not support uid/gid other than root, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	/* we do not allow gid/uid != 0 until we get support for that. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	if ((uid != 0) || (gid != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		pr_warn("Root becomes the owner of all s390dbf files in sysfs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	BUG_ON(!initialized);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	/* create new debug_info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	rc = debug_info_create(name, pages_per_area, nr_areas, buf_size, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 		_debug_register(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		pr_err("Registering debug feature %s failed\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) EXPORT_SYMBOL(debug_register_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672)  * debug_register() - creates and initializes debug area with default file mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674)  * @name:	Name of debug log (e.g. used for debugfs entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675)  * @pages_per_area:	Number of pages, which will be allocated per area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676)  * @nr_areas:	Number of debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677)  * @buf_size:	Size of data area in each debug entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680)  * - Handle for generated debug area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681)  * - %NULL if register failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683)  * Allocates memory for a debug log.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684)  * The debugfs file mode access permissions are read and write for user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685)  * Must not be called within an interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) debug_info_t *debug_register(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 			     int nr_areas, int buf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	return debug_register_mode(name, pages_per_area, nr_areas, buf_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 				   S_IRUSR | S_IWUSR, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) EXPORT_SYMBOL(debug_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) /* Remove debugfs entries and remove from internal list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) static void _debug_unregister(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		if (!id->views[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		debugfs_remove(id->debugfs_entries[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	debugfs_remove(id->debugfs_root_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	if (id == debug_area_first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		debug_area_first = id->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	if (id == debug_area_last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 		debug_area_last = id->prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	if (id->prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		id->prev->next = id->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	if (id->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		id->next->prev = id->prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717)  * debug_unregister() - give back debug area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719)  * @id:		handle for debug log
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722)  *    none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) void debug_unregister(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	_debug_unregister(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	debug_info_put(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) EXPORT_SYMBOL(debug_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737)  * debug_set_size:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738)  * - set area size (number of pages) and number of areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) static int debug_set_size(debug_info_t *id, int nr_areas, int pages_per_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	debug_info_t *new_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	if (!id || (nr_areas <= 0) || (pages_per_area < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	new_id = debug_info_alloc("", pages_per_area, nr_areas, id->buf_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 				  id->level, ALL_AREAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	if (!new_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 		pr_info("Allocating memory for %i pages failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 			pages_per_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	debug_events_append(new_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	debug_areas_swap(new_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	debug_info_free(new_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	pr_info("%s: set new size (%i pages)\n", id->name, pages_per_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767)  * debug_set_level() - Sets new actual debug level if new_level is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769)  * @id:		handle for debug log
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770)  * @new_level:	new debug level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773)  *    none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) void debug_set_level(debug_info_t *id, int new_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	if (new_level == DEBUG_OFF_LEVEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		id->level = DEBUG_OFF_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 		pr_info("%s: switched off\n", id->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	} else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		pr_info("%s: level %i is out of range (%i - %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 			id->name, new_level, 0, DEBUG_MAX_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 		id->level = new_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) EXPORT_SYMBOL(debug_set_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796)  * proceed_active_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797)  * - set active entry to next in the ring buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) static inline void proceed_active_entry(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	if ((id->active_entries[id->active_area] += id->entry_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	    > (PAGE_SIZE - id->entry_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 		id->active_entries[id->active_area] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		id->active_pages[id->active_area] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 			(id->active_pages[id->active_area] + 1) %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 			id->pages_per_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811)  * proceed_active_area:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812)  * - set active area to next in the ring buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) static inline void proceed_active_area(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	id->active_area++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	id->active_area = id->active_area % id->nr_areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821)  * get_active_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) static inline debug_entry_t *get_active_entry(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	return (debug_entry_t *) (((char *) id->areas[id->active_area]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 				   [id->active_pages[id->active_area]]) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 				  id->active_entries[id->active_area]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) /* Swap debug areas of a and b. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) static void debug_areas_swap(debug_info_t *a, debug_info_t *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	swap(a->nr_areas, b->nr_areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	swap(a->pages_per_area, b->pages_per_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	swap(a->areas, b->areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	swap(a->active_area, b->active_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	swap(a->active_pages, b->active_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	swap(a->active_entries, b->active_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) /* Append all debug events in active area from source to destination log. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) static void debug_events_append(debug_info_t *dest, debug_info_t *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	debug_entry_t *from, *to, *last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	if (!src->areas || !dest->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	/* Loop over all entries in src, starting with oldest. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	from = get_active_entry(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	last = from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 		if (from->clock != 0LL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 			to = get_active_entry(dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 			memset(to, 0, dest->entry_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 			memcpy(to, from, min(src->entry_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 					     dest->entry_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 			proceed_active_entry(dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 		proceed_active_entry(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		from = get_active_entry(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	} while (from != last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867)  * debug_finish_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868)  * - set timestamp, caller address, cpu number etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) static inline void debug_finish_entry(debug_info_t *id, debug_entry_t *active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 				      int level, int exception)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 	unsigned char clk[STORE_CLOCK_EXT_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	unsigned long timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	get_tod_clock_ext(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	timestamp = *(unsigned long *) &clk[0] >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	timestamp -= TOD_UNIX_EPOCH >> 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	active->clock = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	active->cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	active->caller = __builtin_return_address(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	active->exception = exception;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	active->level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	proceed_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	if (exception)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 		proceed_active_area(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) static int debug_stoppable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) static int debug_active = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) #define CTL_S390DBF_STOPPABLE 5678
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) #define CTL_S390DBF_ACTIVE 5679
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897)  * proc handler for the running debug_active sysctl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898)  * always allow read, allow write only if debug_stoppable is set or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899)  * if debug_active is already off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) static int s390dbf_procactive(struct ctl_table *table, int write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 			      void *buffer, size_t *lenp, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	if (!write || debug_stoppable || !debug_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		return proc_dointvec(table, write, buffer, lenp, ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) static struct ctl_table s390dbf_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		.procname	= "debug_stoppable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 		.data		= &debug_stoppable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 		.maxlen		= sizeof(int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 		.mode		= S_IRUGO | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		.proc_handler	= proc_dointvec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		.procname	= "debug_active",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		.data		= &debug_active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 		.maxlen		= sizeof(int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		.mode		= S_IRUGO | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		.proc_handler	= s390dbf_procactive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) static struct ctl_table s390dbf_dir_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 		.procname	= "s390dbf",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 		.maxlen		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		.mode		= S_IRUGO | S_IXUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		.child		= s390dbf_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) static struct ctl_table_header *s390dbf_sysctl_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941)  * debug_stop_all() - stops the debug feature if stopping is allowed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944)  * -   none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946)  * Currently used in case of a kernel oops.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) void debug_stop_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	if (debug_stoppable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		debug_active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) EXPORT_SYMBOL(debug_stop_all);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956)  * debug_set_critical() - event/exception functions try lock instead of spin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959)  * -   none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961)  * Currently used in case of stopping all CPUs but the current one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962)  * Once in this state, functions to write a debug entry for an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963)  * event or exception no longer spin on the debug area lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964)  * but only try to get it and fail if they do not get the lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) void debug_set_critical(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	debug_critical = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972)  * debug_event_common:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973)  * - write debug entry with given size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) debug_entry_t *debug_event_common(debug_info_t *id, int level, const void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 				  int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	debug_entry_t *active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	if (!debug_active || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	if (debug_critical) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		if (!spin_trylock_irqsave(&id->lock, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		active = get_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 		if (len < id->buf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 			memset((DEBUG_DATA(active)) + len, 0, id->buf_size - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		debug_finish_entry(id, active, level, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		len -= id->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		buf += id->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	} while (len > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	return active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) EXPORT_SYMBOL(debug_event_common);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)  * debug_exception_common:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)  * - write debug entry with given size and switch to next debug area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) debug_entry_t *debug_exception_common(debug_info_t *id, int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 				      const void *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	debug_entry_t *active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	if (!debug_active || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	if (debug_critical) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		if (!spin_trylock_irqsave(&id->lock, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		active = get_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 		memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		if (len < id->buf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 			memset((DEBUG_DATA(active)) + len, 0, id->buf_size - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 		debug_finish_entry(id, active, level, len <= id->buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		len -= id->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		buf += id->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	} while (len > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	return active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) EXPORT_SYMBOL(debug_exception_common);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)  * counts arguments in format string for sprintf view
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static inline int debug_count_numargs(char *string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	int numargs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	while (*string) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 		if (*string++ == '%')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 			numargs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	return numargs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)  * debug_sprintf_event:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) debug_entry_t *__debug_sprintf_event(debug_info_t *id, int level, char *string, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	debug_sprintf_entry_t *curr_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	debug_entry_t *active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	int numargs, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	if (!debug_active || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	numargs = debug_count_numargs(string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	if (debug_critical) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 		if (!spin_trylock_irqsave(&id->lock, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 		spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	active = get_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 	curr_event = (debug_sprintf_entry_t *) DEBUG_DATA(active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	va_start(ap, string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	curr_event->string = string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	for (idx = 0; idx < min(numargs, (int)(id->buf_size / sizeof(long)) - 1); idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 		curr_event->args[idx] = va_arg(ap, long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 	debug_finish_entry(id, active, level, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	return active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) EXPORT_SYMBOL(__debug_sprintf_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)  * debug_sprintf_exception:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) debug_entry_t *__debug_sprintf_exception(debug_info_t *id, int level, char *string, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	debug_sprintf_entry_t *curr_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	debug_entry_t *active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	int numargs, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 	if (!debug_active || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	numargs = debug_count_numargs(string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 	if (debug_critical) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 		if (!spin_trylock_irqsave(&id->lock, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 		spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 	active = get_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	curr_event = (debug_sprintf_entry_t *)DEBUG_DATA(active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 	va_start(ap, string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 	curr_event->string = string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	for (idx = 0; idx < min(numargs, (int)(id->buf_size / sizeof(long)) - 1); idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 		curr_event->args[idx] = va_arg(ap, long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	debug_finish_entry(id, active, level, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	return active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) EXPORT_SYMBOL(__debug_sprintf_exception);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)  * debug_register_view() - registers new debug view and creates debugfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)  *			   dir entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)  * @id:		handle for debug log
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)  * @view:	pointer to debug view struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)  * -   0  : ok
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)  * -   < 0: Error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) int debug_register_view(debug_info_t *id, struct debug_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	struct dentry *pde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	umode_t mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	mode = (id->mode | S_IFREG) & ~S_IXUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	if (!(view->prolog_proc || view->format_proc || view->header_proc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 		mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	if (!view->input_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 		mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 				  id, &debug_file_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 		if (!id->views[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	if (i == DEBUG_MAX_VIEWS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 		pr_err("Registering view %s/%s would exceed the maximum "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 		       "number of views %i\n", id->name, view->name, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 		rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 		id->views[i] = view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 		id->debugfs_entries[i] = pde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 		debugfs_remove(pde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) EXPORT_SYMBOL(debug_register_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)  * debug_unregister_view() - unregisters debug view and removes debugfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)  *			     dir entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)  * @id:		handle for debug log
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)  * @view:	pointer to debug view struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)  * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)  * -   0  : ok
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)  * -   < 0: Error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) int debug_unregister_view(debug_info_t *id, struct debug_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	struct dentry *dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 		if (id->views[i] == view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	if (i == DEBUG_MAX_VIEWS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 		rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 		dentry = id->debugfs_entries[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		id->views[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 		id->debugfs_entries[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 	spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	debugfs_remove(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) EXPORT_SYMBOL(debug_unregister_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) static inline char *debug_get_user_string(const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 					  size_t user_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	char *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	buffer = kmalloc(user_len + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 	if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	if (copy_from_user(buffer, user_buf, user_len) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 		kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 		return ERR_PTR(-EFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	/* got the string, now strip linefeed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	if (buffer[user_len - 1] == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 		buffer[user_len - 1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		buffer[user_len] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	return buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) static inline int debug_get_uint(char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	buf = skip_spaces(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	rc = simple_strtoul(buf, &buf, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 	if (*buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)  * functions for debug-views
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)  ***********************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)  * prints out actual debug level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) static int debug_prolog_pages_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 				 char *out_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	return sprintf(out_buf, "%i\n", id->pages_per_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)  * reads new size (number of pages per debug area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) static int debug_input_pages_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 				struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 				size_t user_len, loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 	int rc, new_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 	char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	if (user_len > 0x10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 		user_len = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	if (*offset != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 		rc = -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 	str = debug_get_user_string(user_buf, user_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	if (IS_ERR(str)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 		rc = PTR_ERR(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	new_pages = debug_get_uint(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	if (new_pages < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 		goto free_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	rc = debug_set_size(id, id->nr_areas, new_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 		goto free_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 	rc = user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) free_str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 	kfree(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	*offset += user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 	return rc;		/* number of input characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)  * prints out actual debug level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) static int debug_prolog_level_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 				 char *out_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	if (id->level == DEBUG_OFF_LEVEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 		rc = sprintf(out_buf, "-\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 		rc = sprintf(out_buf, "%i\n", id->level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)  * reads new debug level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) static int debug_input_level_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 				struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 				size_t user_len, loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 	int rc, new_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 	char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	if (user_len > 0x10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 		user_len = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	if (*offset != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 		rc = -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 	str = debug_get_user_string(user_buf, user_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	if (IS_ERR(str)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 		rc = PTR_ERR(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	if (str[0] == '-') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 		debug_set_level(id, DEBUG_OFF_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 		rc = user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 		goto free_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 		new_level = debug_get_uint(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 	if (new_level < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 		pr_warn("%s is not a valid level for a debug feature\n", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 		debug_set_level(id, new_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 		rc = user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) free_str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 	kfree(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 	*offset += user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 	return rc;		/* number of input characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)  * flushes debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) static void debug_flush(debug_info_t *id, int area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 	if (!id || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 	spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	if (area == DEBUG_FLUSH_ALL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 		id->active_area = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 		memset(id->active_entries, 0, id->nr_areas * sizeof(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 		for (i = 0; i < id->nr_areas; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 			id->active_pages[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 			for (j = 0; j < id->pages_per_area; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 				memset(id->areas[i][j], 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 	} else if (area >= 0 && area < id->nr_areas) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 		id->active_entries[area] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 		id->active_pages[area] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 		for (i = 0; i < id->pages_per_area; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 			memset(id->areas[area][i], 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 	spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)  * view function: flushes debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 				struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 				size_t user_len, loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	char input_buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	int rc = user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 	if (user_len > 0x10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 		user_len = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	if (*offset != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 		rc = -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 	if (copy_from_user(input_buf, user_buf, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 		rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 	if (input_buf[0] == '-') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 		debug_flush(id, DEBUG_FLUSH_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 	if (isdigit(input_buf[0])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 		int area = ((int) input_buf[0] - (int) '0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 		debug_flush(id, area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 	pr_info("Flushing debug data failed because %c is not a valid "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 		 "area\n", input_buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 	*offset += user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 	return rc;		/* number of input characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)  * prints debug data in hex/ascii format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 				     char *out_buf, const char *in_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 	int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 	for (i = 0; i < id->buf_size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 		rc += sprintf(out_buf + rc, "%02x ", ((unsigned char *) in_buf)[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 	rc += sprintf(out_buf + rc, "| ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 	for (i = 0; i < id->buf_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 		unsigned char c = in_buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 		if (isascii(c) && isprint(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 			rc += sprintf(out_buf + rc, "%c", c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 			rc += sprintf(out_buf + rc, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 	rc += sprintf(out_buf + rc, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)  * prints header for debug entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 			 int area, debug_entry_t *entry, char *out_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 	unsigned long sec, usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 	unsigned long caller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 	unsigned int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 	char *except_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 	level = entry->level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 	sec = entry->clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 	usec = do_div(sec, USEC_PER_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 	if (entry->exception)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 		except_str = "*";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 		except_str = "-";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	caller = (unsigned long) entry->caller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 	rc += sprintf(out_buf, "%02i %011ld:%06lu %1u %1s %04u %pK  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 		      area, sec, usec, level, except_str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 		      entry->cpu, (void *)caller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) EXPORT_SYMBOL(debug_dflt_header_fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)  * prints debug data sprintf-formated:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)  * debug_sprinf_event/exception calls must be used together with this view
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) #define DEBUG_SPRINTF_MAX_ARGS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 				   char *out_buf, debug_sprintf_entry_t *curr_event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 	int num_longs, num_used_args = 0, i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 	int index[DEBUG_SPRINTF_MAX_ARGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 	/* count of longs fit into one entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 	num_longs = id->buf_size / sizeof(long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 	if (num_longs < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 		goto out; /* bufsize of entry too small */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 	if (num_longs == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 		/* no args, we use only the string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 		strcpy(out_buf, curr_event->string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 		rc = strlen(curr_event->string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 	/* number of arguments used for sprintf (without the format string) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 	num_used_args = min(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 	memset(index, 0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	for (i = 0; i < num_used_args; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 		index[i] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 	rc = sprintf(out_buf, curr_event->string, curr_event->args[index[0]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 		     curr_event->args[index[1]], curr_event->args[index[2]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 		     curr_event->args[index[3]], curr_event->args[index[4]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 		     curr_event->args[index[5]], curr_event->args[index[6]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 		     curr_event->args[index[7]], curr_event->args[index[8]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 		     curr_event->args[index[9]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)  * debug_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)  * - is called exactly once to initialize the debug feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) static int __init debug_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 	mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 	debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 	initialized = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 	mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) postcore_initcall(debug_init);