blob: 5c1937f3af07945ed14952639dfbca7ddc8a41e0 [file] [log] [blame]
/* Copyright (c) 2012-2015,2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _IPC_LOGGING_H
#define _IPC_LOGGING_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 defined(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
* @user_version : Version number of user-defined message formats
*
* returns context id on success, NULL on failure
*/
void *ipc_log_context_create(int max_num_pages, const char *modname,
uint16_t user_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_int32_write: Writes a 32-bit integer value
*
* @ectxt: Context initialized by calling msg_encode_start()
* @n: Integer to write
*/
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);
/*
* msg_encode_end: Complete the message encode process
*
* @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_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
*/
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, uint16_t user_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