summaryrefslogtreecommitdiff
path: root/inc/ipc_logging.h
blob: e60492fc81e884c6949b2b00701643886ef66670 (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
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2012-2015,2017,2020 The Linux Foundation. All rights reserved.
 */

#ifndef _IPC_LOGGING_H
#define _IPC_LOGGING_H

#include <linux/errno.h>
#include <linux/types.h>

#define MAX_MSG_SIZE 255

enum {
	TSV_TYPE_MSG_START = 1,
	TSV_TYPE_SKB = TSV_TYPE_MSG_START,
	TSV_TYPE_STRING,
	TSV_TYPE_MSG_END = TSV_TYPE_STRING,
};

struct tsv_header {
	unsigned char type;
	unsigned char size; /* size of data field */
};

struct encode_context {
	struct tsv_header hdr;
	char buff[MAX_MSG_SIZE];
	int offset;
};

struct decode_context {
	int output_format;      /* 0 = debugfs */
	char *buff;             /* output buffer */
	int size;               /* size of output buffer */
};

#if IS_ENABLED(CONFIG_IPC_LOGGING)
/*
 * ipc_log_context_create: Create a debug log context
 *                         Should not be called from atomic context
 *
 * @max_num_pages: Number of pages of logging space required (max. 10)
 * @mod_name     : Name of the directory entry under DEBUGFS
 * @feature_version : First 16 bit for version number of user-defined message
 *		      formats and next 16 bit for enabling minidump
 *
 * returns context id on success, NULL on failure
 */
void *ipc_log_context_create(int max_num_pages, const char *modname,
		uint32_t feature_version);

/*
 * msg_encode_start: Start encoding a log message
 *
 * @ectxt: Temporary storage to hold the encoded message
 * @type:  Root event type defined by the module which is logging
 */
void msg_encode_start(struct encode_context *ectxt, uint32_t type);

/*
 * tsv_timestamp_write: Writes the current timestamp count
 *
 * @ectxt: Context initialized by calling msg_encode_start()
 */
int tsv_timestamp_write(struct encode_context *ectxt);

/*
 * tsv_qtimer_write: Writes the current QTimer timestamp count
 *
 * @ectxt: Context initialized by calling msg_encode_start()
 */
int tsv_qtimer_write(struct encode_context *ectxt);

/*
 * tsv_pointer_write: Writes a data pointer
 *
 * @ectxt:   Context initialized by calling msg_encode_start()
 * @pointer: Pointer value to write
 */
int tsv_pointer_write(struct encode_context *ectxt, void *pointer);

/*
 * tsv_int32_write: Writes a 32-bit integer value
 *
 * @ectxt: Context initialized by calling msg_encode_start()
 * @n:     Integer to write
 */
int tsv_int32_write(struct encode_context *ectxt, int32_t n);

/*
 * tsv_byte_array_write: Writes a byte array
 *
 * @ectxt:     Context initialized by calling msg_encode_start()
 * @data:      Pointer to byte array
 * @data_size: Size of byte array
 */
int tsv_byte_array_write(struct encode_context *ectxt,
			 void *data, int data_size);

/*
 * msg_encode_end: Complete the message encode process
 *
 * @ectxt: Temporary storage which holds the encoded message
 */
void msg_encode_end(struct encode_context *ectxt);

/*
 * ipc_log_write: Commits message to logging ring buffer
 *
 * @ctxt:  Logging context
 * @ectxt: Temporary storage which holds the encoded message
 */
void ipc_log_write(void *ctxt, struct encode_context *ectxt);

/*
 * ipc_log_string: Helper function to log a string
 *
 * @ilctxt: Debug Log Context created using ipc_log_context_create()
 * @fmt:    Data specified using format specifiers
 */
int ipc_log_string(void *ilctxt, const char *fmt, ...) __printf(2, 3);

/**
 * ipc_log_extract - Reads and deserializes log
 *
 * @ilctxt:  logging context
 * @buff:    buffer to receive the data
 * @size:    size of the buffer
 * @returns: 0 if no data read; >0 number of bytes read; < 0 error
 *
 * If no data is available to be read, then the ilctxt::read_avail
 * completion is reinitialized.  This allows clients to block
 * until new log data is save.
 */
int ipc_log_extract(void *ilctxt, char *buff, int size);

/*
 * Print a string to decode context.
 * @dctxt   Decode context
 * @args   printf args
 */
#define IPC_SPRINTF_DECODE(dctxt, args...) \
do { \
	int i; \
	i = scnprintf(dctxt->buff, dctxt->size, args); \
	dctxt->buff += i; \
	dctxt->size -= i; \
} while (0)

/*
 * tsv_timestamp_read: Reads a timestamp
 *
 * @ectxt:  Context retrieved by reading from log space
 * @dctxt:  Temporary storage to hold the decoded message
 * @format: Output format while dumping through DEBUGFS
 */
void tsv_timestamp_read(struct encode_context *ectxt,
			struct decode_context *dctxt, const char *format);

/*
 * tsv_qtimer_read: Reads a QTimer timestamp
 *
 * @ectxt:  Context retrieved by reading from log space
 * @dctxt:  Temporary storage to hold the decoded message
 * @format: Output format while dumping through DEBUGFS
 */
void tsv_qtimer_read(struct encode_context *ectxt,
		     struct decode_context *dctxt, const char *format);

/*
 * tsv_pointer_read: Reads a data pointer
 *
 * @ectxt:  Context retrieved by reading from log space
 * @dctxt:  Temporary storage to hold the decoded message
 * @format: Output format while dumping through DEBUGFS
 */
void tsv_pointer_read(struct encode_context *ectxt,
		      struct decode_context *dctxt, const char *format);

/*
 * tsv_int32_read: Reads a 32-bit integer value
 *
 * @ectxt:  Context retrieved by reading from log space
 * @dctxt:  Temporary storage to hold the decoded message
 * @format: Output format while dumping through DEBUGFS
 */
int32_t tsv_int32_read(struct encode_context *ectxt,
		       struct decode_context *dctxt, const char *format);

/*
 * tsv_byte_array_read: Reads a byte array
 *
 * @ectxt:  Context retrieved by reading from log space
 * @dctxt:  Temporary storage to hold the decoded message
 * @format: Output format while dumping through DEBUGFS
 */
void tsv_byte_array_read(struct encode_context *ectxt,
			 struct decode_context *dctxt, const char *format);

/*
 * add_deserialization_func: Register a deserialization function to
 *                           to unpack the subevents of a main event
 *
 * @ctxt: Debug log context to which the deserialization function has
 *        to be registered
 * @type: Main/Root event, defined by the module which is logging, to
 *        which this deserialization function has to be registered.
 * @dfune: Deserialization function to be registered
 *
 * return 0 on success, -ve value on FAILURE
 */
int add_deserialization_func(void *ctxt, int type,
			void (*dfunc)(struct encode_context *,
				      struct decode_context *));

/*
 * ipc_log_context_destroy: Destroy debug log context
 *
 * @ctxt: debug log context created by calling ipc_log_context_create API.
 */
int ipc_log_context_destroy(void *ctxt);

#else

static inline void *ipc_log_context_create(int max_num_pages,
	const char *modname, uint32_t feature_version)
{ return NULL; }

static inline void msg_encode_start(struct encode_context *ectxt,
	uint32_t type) { }

static inline int tsv_timestamp_write(struct encode_context *ectxt)
{ return -EINVAL; }

static inline int tsv_qtimer_write(struct encode_context *ectxt)
{ return -EINVAL; }

static inline int tsv_pointer_write(struct encode_context *ectxt, void *pointer)
{ return -EINVAL; }

static inline int tsv_int32_write(struct encode_context *ectxt, int32_t n)
{ return -EINVAL; }

static inline int tsv_byte_array_write(struct encode_context *ectxt,
			 void *data, int data_size)
{ return -EINVAL; }

static inline void msg_encode_end(struct encode_context *ectxt) { }

static inline void ipc_log_write(void *ctxt, struct encode_context *ectxt) { }

static inline int ipc_log_string(void *ilctxt, const char *fmt, ...)
{ return -EINVAL; }

static inline int ipc_log_extract(void *ilctxt, char *buff, int size)
{ return -EINVAL; }

#define IPC_SPRINTF_DECODE(dctxt, args...) do { } while (0)

static inline void tsv_timestamp_read(struct encode_context *ectxt,
			struct decode_context *dctxt, const char *format) { }

static inline void tsv_qtimer_read(struct encode_context *ectxt,
			struct decode_context *dctxt, const char *format) { }

static inline void tsv_pointer_read(struct encode_context *ectxt,
		      struct decode_context *dctxt, const char *format) { }

static inline int32_t tsv_int32_read(struct encode_context *ectxt,
		       struct decode_context *dctxt, const char *format)
{ return 0; }

static inline void tsv_byte_array_read(struct encode_context *ectxt,
			 struct decode_context *dctxt, const char *format) { }

static inline int add_deserialization_func(void *ctxt, int type,
			void (*dfunc)(struct encode_context *,
				      struct decode_context *))
{ return 0; }

static inline int ipc_log_context_destroy(void *ctxt)
{ return 0; }

#endif

#endif