summaryrefslogtreecommitdiff
path: root/msm/sde_dbg.h
blob: e336f3236978859b5797e6c6c3671f60707ec054 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 */

#ifndef SDE_DBG_H_
#define SDE_DBG_H_

#include <stdarg.h>
#include <linux/debugfs.h>
#include <linux/list.h>

/* select an uncommon hex value for the limiter */
#define SDE_EVTLOG_DATA_LIMITER	(0xC0DEBEEF)
#define SDE_EVTLOG_FUNC_ENTRY	0x1111
#define SDE_EVTLOG_FUNC_EXIT	0x2222
#define SDE_EVTLOG_FUNC_CASE1	0x3333
#define SDE_EVTLOG_FUNC_CASE2	0x4444
#define SDE_EVTLOG_FUNC_CASE3	0x5555
#define SDE_EVTLOG_FUNC_CASE4	0x6666
#define SDE_EVTLOG_FUNC_CASE5	0x7777
#define SDE_EVTLOG_FUNC_CASE6	0x8888
#define SDE_EVTLOG_FUNC_CASE7	0x9999
#define SDE_EVTLOG_FUNC_CASE8	0xaaaa
#define SDE_EVTLOG_FUNC_CASE9	0xbbbb
#define SDE_EVTLOG_FUNC_CASE10	0xcccc
#define SDE_EVTLOG_PANIC	0xdead
#define SDE_EVTLOG_FATAL	0xbad
#define SDE_EVTLOG_ERROR	0xebad

#define SDE_DBG_DUMP_DATA_LIMITER (NULL)

enum sde_dbg_evtlog_flag {
	SDE_EVTLOG_CRITICAL = BIT(0),
	SDE_EVTLOG_IRQ = BIT(1),
	SDE_EVTLOG_VERBOSE = BIT(2),
	SDE_EVTLOG_EXTERNAL = BIT(3),
	SDE_EVTLOG_ALWAYS = -1
};

enum sde_dbg_dump_flag {
	SDE_DBG_DUMP_IN_LOG = BIT(0),
	SDE_DBG_DUMP_IN_MEM = BIT(1),
};

enum sde_dbg_dump_context {
	SDE_DBG_DUMP_PROC_CTX,
	SDE_DBG_DUMP_IRQ_CTX,
	SDE_DBG_DUMP_CLK_ENABLED_CTX,
};

#define SDE_EVTLOG_DEFAULT_ENABLE (SDE_EVTLOG_CRITICAL | SDE_EVTLOG_IRQ | \
		SDE_EVTLOG_EXTERNAL)

/*
 * evtlog will print this number of entries when it is called through
 * sysfs node or panic. This prevents kernel log from evtlog message
 * flood.
 */
#define SDE_EVTLOG_PRINT_ENTRY	256

/*
 * evtlog keeps this number of entries in memory for debug purpose. This
 * number must be greater than print entry to prevent out of bound evtlog
 * entry array access.
 */
#define SDE_EVTLOG_ENTRY	(SDE_EVTLOG_PRINT_ENTRY * 32)
#define SDE_EVTLOG_MAX_DATA 15
#define SDE_EVTLOG_BUF_MAX 512
#define SDE_EVTLOG_BUF_ALIGN 32

struct sde_dbg_power_ctrl {
	void *handle;
	void *client;
	int (*enable_fn)(void *handle, void *client, bool enable);
};

struct sde_dbg_evtlog_log {
	s64 time;
	const char *name;
	int line;
	u32 data[SDE_EVTLOG_MAX_DATA];
	u32 data_cnt;
	int pid;
	u8 cpu;
};

/**
 * @last_dump: Index of last entry to be output during evtlog dumps
 * @filter_list: Linked list of currently active filter strings
 */
struct sde_dbg_evtlog {
	struct sde_dbg_evtlog_log logs[SDE_EVTLOG_ENTRY];
	u32 first;
	u32 last;
	u32 last_dump;
	u32 curr;
	u32 next;
	u32 enable;
	spinlock_t spin_lock;
	struct list_head filter_list;
};

extern struct sde_dbg_evtlog *sde_dbg_base_evtlog;

/**
 * SDE_EVT32 - Write a list of 32bit values to the event log, default area
 * ... - variable arguments
 */
#define SDE_EVT32(...) sde_evtlog_log(sde_dbg_base_evtlog, __func__, \
		__LINE__, SDE_EVTLOG_ALWAYS, ##__VA_ARGS__, \
		SDE_EVTLOG_DATA_LIMITER)

/**
 * SDE_EVT32_VERBOSE - Write a list of 32bit values for verbose event logging
 * ... - variable arguments
 */
#define SDE_EVT32_VERBOSE(...) sde_evtlog_log(sde_dbg_base_evtlog, __func__, \
		__LINE__, SDE_EVTLOG_VERBOSE, ##__VA_ARGS__, \
		SDE_EVTLOG_DATA_LIMITER)

/**
 * SDE_EVT32_IRQ - Write a list of 32bit values to the event log, IRQ area
 * ... - variable arguments
 */
#define SDE_EVT32_IRQ(...) sde_evtlog_log(sde_dbg_base_evtlog, __func__, \
		__LINE__, SDE_EVTLOG_IRQ, ##__VA_ARGS__, \
		SDE_EVTLOG_DATA_LIMITER)

/**
 * SDE_EVT32_EXTERNAL - Write a list of 32bit values for external display events
 * ... - variable arguments
 */
#define SDE_EVT32_EXTERNAL(...) sde_evtlog_log(sde_dbg_base_evtlog, __func__, \
		__LINE__, SDE_EVTLOG_EXTERNAL, ##__VA_ARGS__, \
		SDE_EVTLOG_DATA_LIMITER)

/**
 * SDE_DBG_DUMP - trigger dumping of all sde_dbg facilities
 * @va_args:	list of named register dump ranges and regions to dump, as
 *		registered previously through sde_dbg_reg_register_base and
 *		sde_dbg_reg_register_dump_range.
 *		Including the special name "panic" will trigger a panic after
 *		the dumping work has completed.
 */
#define SDE_DBG_DUMP(...) sde_dbg_dump(SDE_DBG_DUMP_PROC_CTX, __func__, \
		##__VA_ARGS__, SDE_DBG_DUMP_DATA_LIMITER)

/**
 * SDE_DBG_DUMP_WQ - trigger dumping of all sde_dbg facilities, queuing the work
 * @va_args:	list of named register dump ranges and regions to dump, as
 *		registered previously through sde_dbg_reg_register_base and
 *		sde_dbg_reg_register_dump_range.
 *		Including the special name "panic" will trigger a panic after
 *		the dumping work has completed.
 */
#define SDE_DBG_DUMP_WQ(...) sde_dbg_dump(SDE_DBG_DUMP_IRQ_CTX, __func__, \
		##__VA_ARGS__, SDE_DBG_DUMP_DATA_LIMITER)

/**
 * SDE_DBG_DUMP_CLK_EN - trigger dumping of all sde_dbg facilities, without clk
 * @va_args:	list of named register dump ranges and regions to dump, as
 *		registered previously through sde_dbg_reg_register_base and
 *		sde_dbg_reg_register_dump_range.
 *		Including the special name "panic" will trigger a panic after
 *		the dumping work has completed.
 */
#define SDE_DBG_DUMP_CLK_EN(...) sde_dbg_dump(SDE_DBG_DUMP_CLK_ENABLED_CTX, \
		__func__, ##__VA_ARGS__, SDE_DBG_DUMP_DATA_LIMITER)

/**
 * SDE_DBG_EVT_CTRL - trigger a different driver events
 *  event: event that trigger different behavior in the driver
 */
#define SDE_DBG_CTRL(...) sde_dbg_ctrl(__func__, ##__VA_ARGS__, \
		SDE_DBG_DUMP_DATA_LIMITER)

#if defined(CONFIG_DEBUG_FS)

/**
 * sde_evtlog_init - allocate a new event log object
 * Returns:	evtlog or -ERROR
 */
struct sde_dbg_evtlog *sde_evtlog_init(void);

/**
 * sde_evtlog_destroy - destroy previously allocated event log
 * @evtlog:	pointer to evtlog
 * Returns:	none
 */
void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog);

/**
 * sde_evtlog_log - log an entry into the event log.
 *	log collection may be enabled/disabled entirely via debugfs
 *	log area collection may be filtered by user provided flags via debugfs.
 * @evtlog:	pointer to evtlog
 * @name:	function name of call site
 * @line:	line number of call site
 * @flag:	log area filter flag checked against user's debugfs request
 * Returns:	none
 */
void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, const char *name, int line,
		int flag, ...);

/**
 * sde_evtlog_dump_all - print all entries in event log to kernel log
 * @evtlog:	pointer to evtlog
 * Returns:	none
 */
void sde_evtlog_dump_all(struct sde_dbg_evtlog *evtlog);

/**
 * sde_evtlog_is_enabled - check whether log collection is enabled for given
 *	event log and log area flag
 * @evtlog:	pointer to evtlog
 * @flag:	log area filter flag
 * Returns:	none
 */
bool sde_evtlog_is_enabled(struct sde_dbg_evtlog *evtlog, u32 flag);

/**
 * sde_evtlog_dump_to_buffer - print content of event log to the given buffer
 * @evtlog:		pointer to evtlog
 * @evtlog_buf:		target buffer to print into
 * @evtlog_buf_size:	size of target buffer
 * @update_last_entry:	whether or not to stop at most recent entry
 * @full_dump:          whether to dump full or to limit print entries
 * Returns:		number of bytes written to buffer
 */
ssize_t sde_evtlog_dump_to_buffer(struct sde_dbg_evtlog *evtlog,
		char *evtlog_buf, ssize_t evtlog_buf_size,
		bool update_last_entry, bool full_dump);

/**
 * sde_dbg_init_dbg_buses - initialize debug bus dumping support for the chipset
 * @hwversion:		Chipset revision
 */
void sde_dbg_init_dbg_buses(u32 hwversion);

/**
 * sde_dbg_init - initialize global sde debug facilities: evtlog, regdump
 * @dev:		device handle
 * Returns:		0 or -ERROR
 */
int sde_dbg_init(struct device *dev);

/**
 * sde_dbg_debugfs_register - register entries at the given debugfs dir
 * @debugfs_root:	debugfs root in which to create sde debug entries
 * Returns:	0 or -ERROR
 */
int sde_dbg_debugfs_register(struct device *dev);

/**
 * sde_dbg_destroy - destroy the global sde debug facilities
 * Returns:	none
 */
void sde_dbg_destroy(void);

/**
 * sde_dbg_dump - trigger dumping of all sde_dbg facilities
 * @queue_work:	whether to queue the dumping work to the work_struct
 * @name:	string indicating origin of dump
 * @va_args:	list of named register dump ranges and regions to dump, as
 *		registered previously through sde_dbg_reg_register_base and
 *		sde_dbg_reg_register_dump_range.
 *		Including the special name "panic" will trigger a panic after
 *		the dumping work has completed.
 * Returns:	none
 */
void sde_dbg_dump(enum sde_dbg_dump_context mode, const char *name, ...);

/**
 * sde_dbg_ctrl - trigger specific actions for the driver with debugging
 *		purposes. Those actions need to be enabled by the debugfs entry
 *		so the driver executes those actions in the corresponding calls.
 * @va_args:	list of actions to trigger
 * Returns:	none
 */
void sde_dbg_ctrl(const char *name, ...);

/**
 * sde_dbg_reg_register_base - register a hw register address section for later
 *	dumping. call this before calling sde_dbg_reg_register_dump_range
 *	to be able to specify sub-ranges within the base hw range.
 * @name:	name of base region
 * @base:	base pointer of region
 * @max_offset:	length of region
 * Returns:	0 or -ERROR
 */
int sde_dbg_reg_register_base(const char *name, void __iomem *base,
		size_t max_offset);

/**
 * sde_dbg_reg_register_cb - register a hw register callback for later
 *	dumping.
 * @name:	name of base region
 * @cb:		callback of external region
 * @cb_ptr:	private pointer of external region
 * Returns:	0 or -ERROR
 */
int sde_dbg_reg_register_cb(const char *name, void (*cb)(void *), void *ptr);

/**
 * sde_dbg_reg_unregister_cb - register a hw unregister callback for later
 *	dumping.
 * @name:	name of base region
 * @cb:		callback of external region
 * @cb_ptr:	private pointer of external region
 * Returns:	None
 */
void sde_dbg_reg_unregister_cb(const char *name, void (*cb)(void *), void *ptr);

/**
 * sde_dbg_reg_register_dump_range - register a hw register sub-region for
 *	later register dumping associated with base specified by
 *	sde_dbg_reg_register_base
 * @base_name:		name of base region
 * @range_name:		name of sub-range within base region
 * @offset_start:	sub-range's start offset from base's base pointer
 * @offset_end:		sub-range's end offset from base's base pointer
 * @xin_id:		xin id
 * Returns:		none
 */
void sde_dbg_reg_register_dump_range(const char *base_name,
		const char *range_name, u32 offset_start, u32 offset_end,
		uint32_t xin_id);

/**
 * sde_dbg_set_sde_top_offset - set the target specific offset from mdss base
 *	address of the top registers. Used for accessing debug bus controls.
 * @blk_off: offset from mdss base of the top block
 */
void sde_dbg_set_sde_top_offset(u32 blk_off);

/**
 * sde_evtlog_set_filter - update evtlog filtering
 * @evtlog:	pointer to evtlog
 * @filter:     pointer to optional function name filter, set to NULL to disable
 */
void sde_evtlog_set_filter(struct sde_dbg_evtlog *evtlog, char *filter);

/**
 * sde_evtlog_get_filter - query configured evtlog filters
 * @evtlog:	pointer to evtlog
 * @index:	filter index to retrieve
 * @buf:	pointer to output filter buffer
 * @bufsz:	size of output filter buffer
 * Returns:	zero if a filter string was returned
 */
int sde_evtlog_get_filter(struct sde_dbg_evtlog *evtlog, int index,
		char *buf, size_t bufsz);

#ifndef CONFIG_DRM_SDE_RSC
static inline void sde_rsc_debug_dump(u32 mux_sel)
{
}
#else
/**
 * sde_rsc_debug_dump - sde rsc debug dump status
 * @mux_sel:»       select mux on rsc debug bus
 */
void sde_rsc_debug_dump(u32 mux_sel);
#endif

/**
 * dsi_ctrl_debug_dump - dump dsi debug dump status
 * @entries:	array of debug bus control values
 * @size:	size of the debug bus control array
 */
void dsi_ctrl_debug_dump(u32 *entries, u32 size);

#else
static inline struct sde_dbg_evtlog *sde_evtlog_init(void)
{
	return NULL;
}

static inline void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog)
{
}

static inline void sde_evtlog_log(struct sde_dbg_evtlog *evtlog,
		const char *name, int line, int flag, ...)
{
}

static inline void sde_evtlog_dump_all(struct sde_dbg_evtlog *evtlog)
{
}

static inline bool sde_evtlog_is_enabled(struct sde_dbg_evtlog *evtlog,
		u32 flag)
{
	return false;
}

static inline ssize_t sde_evtlog_dump_to_buffer(struct sde_dbg_evtlog *evtlog,
		char *evtlog_buf, ssize_t evtlog_buf_size,
		bool update_last_entry)
{
	return 0;
}

static inline void sde_dbg_init_dbg_buses(u32 hwversion)
{
}

static inline int sde_dbg_init(struct device *dev)
{
	return 0;
}

static inline int sde_dbg_debugfs_register(struct device *dev)
{
	return 0;
}

static inline void sde_dbg_destroy(void)
{
}

static inline void sde_dbg_dump(enum sde_dbg_dump_context mode,
	const char *name, ...)
{
}

static inline void sde_dbg_ctrl(const char *name, ...)
{
}

static inline int sde_dbg_reg_register_base(const char *name,
		void __iomem *base, size_t max_offset)
{
	return 0;
}

static inline void sde_dbg_reg_register_dump_range(const char *base_name,
		const char *range_name, u32 offset_start, u32 offset_end,
		uint32_t xin_id)
{
}

static inline void sde_dbg_set_sde_top_offset(u32 blk_off)
{
}

static inline void sde_evtlog_set_filter(
		struct sde_dbg_evtlog *evtlog, char *filter)
{
}

static inline int sde_evtlog_get_filter(struct sde_dbg_evtlog *evtlog,
		int index, char *buf, size_t bufsz)
{
	return -EINVAL;
}

static inline void sde_rsc_debug_dump(u32 mux_sel)
{
}

static inline void dsi_ctrl_debug_dump(u32 *entries, u32 size)
{
}

#endif /* defined(CONFIG_DEBUG_FS) */


#endif /* SDE_DBG_H_ */