1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Kernel module for testing dynamic_debug |
4 | * |
5 | * Authors: |
6 | * Jim Cromie <jim.cromie@gmail.com> |
7 | */ |
8 | |
9 | #define pr_fmt(fmt) "test_dd: " fmt |
10 | |
11 | #include <linux/module.h> |
12 | |
13 | /* run tests by reading or writing sysfs node: do_prints */ |
14 | |
15 | static void do_prints(void); /* device under test */ |
16 | static int param_set_do_prints(const char *instr, const struct kernel_param *kp) |
17 | { |
18 | do_prints(); |
19 | return 0; |
20 | } |
21 | static int param_get_do_prints(char *buffer, const struct kernel_param *kp) |
22 | { |
23 | do_prints(); |
24 | return scnprintf(buf: buffer, PAGE_SIZE, fmt: "did do_prints\n" ); |
25 | } |
26 | static const struct kernel_param_ops param_ops_do_prints = { |
27 | .set = param_set_do_prints, |
28 | .get = param_get_do_prints, |
29 | }; |
30 | module_param_cb(do_prints, ¶m_ops_do_prints, NULL, 0600); |
31 | |
32 | /* |
33 | * Using the CLASSMAP api: |
34 | * - classmaps must have corresponding enum |
35 | * - enum symbols must match/correlate with class-name strings in the map. |
36 | * - base must equal enum's 1st value |
37 | * - multiple maps must set their base to share the 0-30 class_id space !! |
38 | * (build-bug-on tips welcome) |
39 | * Additionally, here: |
40 | * - tie together sysname, mapname, bitsname, flagsname |
41 | */ |
42 | #define DD_SYS_WRAP(_model, _flags) \ |
43 | static unsigned long bits_##_model; \ |
44 | static struct ddebug_class_param _flags##_model = { \ |
45 | .bits = &bits_##_model, \ |
46 | .flags = #_flags, \ |
47 | .map = &map_##_model, \ |
48 | }; \ |
49 | module_param_cb(_flags##_##_model, ¶m_ops_dyndbg_classes, &_flags##_model, 0600) |
50 | |
51 | /* numeric input, independent bits */ |
52 | enum cat_disjoint_bits { |
53 | D2_CORE = 0, |
54 | D2_DRIVER, |
55 | D2_KMS, |
56 | D2_PRIME, |
57 | D2_ATOMIC, |
58 | D2_VBL, |
59 | D2_STATE, |
60 | D2_LEASE, |
61 | D2_DP, |
62 | D2_DRMRES }; |
63 | DECLARE_DYNDBG_CLASSMAP(map_disjoint_bits, DD_CLASS_TYPE_DISJOINT_BITS, 0, |
64 | "D2_CORE" , |
65 | "D2_DRIVER" , |
66 | "D2_KMS" , |
67 | "D2_PRIME" , |
68 | "D2_ATOMIC" , |
69 | "D2_VBL" , |
70 | "D2_STATE" , |
71 | "D2_LEASE" , |
72 | "D2_DP" , |
73 | "D2_DRMRES" ); |
74 | DD_SYS_WRAP(disjoint_bits, p); |
75 | DD_SYS_WRAP(disjoint_bits, T); |
76 | |
77 | /* symbolic input, independent bits */ |
78 | enum cat_disjoint_names { LOW = 11, MID, HI }; |
79 | DECLARE_DYNDBG_CLASSMAP(map_disjoint_names, DD_CLASS_TYPE_DISJOINT_NAMES, 10, |
80 | "LOW" , "MID" , "HI" ); |
81 | DD_SYS_WRAP(disjoint_names, p); |
82 | DD_SYS_WRAP(disjoint_names, T); |
83 | |
84 | /* numeric verbosity, V2 > V1 related */ |
85 | enum cat_level_num { V0 = 14, V1, V2, V3, V4, V5, V6, V7 }; |
86 | DECLARE_DYNDBG_CLASSMAP(map_level_num, DD_CLASS_TYPE_LEVEL_NUM, 14, |
87 | "V0" , "V1" , "V2" , "V3" , "V4" , "V5" , "V6" , "V7" ); |
88 | DD_SYS_WRAP(level_num, p); |
89 | DD_SYS_WRAP(level_num, T); |
90 | |
91 | /* symbolic verbosity */ |
92 | enum cat_level_names { L0 = 22, L1, L2, L3, L4, L5, L6, L7 }; |
93 | DECLARE_DYNDBG_CLASSMAP(map_level_names, DD_CLASS_TYPE_LEVEL_NAMES, 22, |
94 | "L0" , "L1" , "L2" , "L3" , "L4" , "L5" , "L6" , "L7" ); |
95 | DD_SYS_WRAP(level_names, p); |
96 | DD_SYS_WRAP(level_names, T); |
97 | |
98 | /* stand-in for all pr_debug etc */ |
99 | #define prdbg(SYM) __pr_debug_cls(SYM, #SYM " msg\n") |
100 | |
101 | static void do_cats(void) |
102 | { |
103 | pr_debug("doing categories\n" ); |
104 | |
105 | prdbg(LOW); |
106 | prdbg(MID); |
107 | prdbg(HI); |
108 | |
109 | prdbg(D2_CORE); |
110 | prdbg(D2_DRIVER); |
111 | prdbg(D2_KMS); |
112 | prdbg(D2_PRIME); |
113 | prdbg(D2_ATOMIC); |
114 | prdbg(D2_VBL); |
115 | prdbg(D2_STATE); |
116 | prdbg(D2_LEASE); |
117 | prdbg(D2_DP); |
118 | prdbg(D2_DRMRES); |
119 | } |
120 | |
121 | static void do_levels(void) |
122 | { |
123 | pr_debug("doing levels\n" ); |
124 | |
125 | prdbg(V1); |
126 | prdbg(V2); |
127 | prdbg(V3); |
128 | prdbg(V4); |
129 | prdbg(V5); |
130 | prdbg(V6); |
131 | prdbg(V7); |
132 | |
133 | prdbg(L1); |
134 | prdbg(L2); |
135 | prdbg(L3); |
136 | prdbg(L4); |
137 | prdbg(L5); |
138 | prdbg(L6); |
139 | prdbg(L7); |
140 | } |
141 | |
142 | static void do_prints(void) |
143 | { |
144 | do_cats(); |
145 | do_levels(); |
146 | } |
147 | |
148 | static int __init test_dynamic_debug_init(void) |
149 | { |
150 | pr_debug("init start\n" ); |
151 | do_prints(); |
152 | pr_debug("init done\n" ); |
153 | return 0; |
154 | } |
155 | |
156 | static void __exit test_dynamic_debug_exit(void) |
157 | { |
158 | pr_debug("exited\n" ); |
159 | } |
160 | |
161 | module_init(test_dynamic_debug_init); |
162 | module_exit(test_dynamic_debug_exit); |
163 | |
164 | MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>" ); |
165 | MODULE_LICENSE("GPL" ); |
166 | |