/* Copyright (c) 2012-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_PRIVATE_H #define _IPC_LOGGING_PRIVATE_H #include #define IPC_LOG_VERSION 0x0003 #define IPC_LOG_MAX_CONTEXT_NAME_LEN 32 /** * struct ipc_log_page_header - Individual log page header * * @magic: Magic number (used for log extraction) * @nmagic: Inverse of magic number (used for log extraction) * @page_num: Index of page (0.. N - 1) (note top bit is always set) * @read_offset: Read offset in page * @write_offset: Write offset in page (or 0xFFFF if full) * @log_id: ID of logging context that owns this page * @start_time: Scheduler clock for first write time in page * @end_time: Scheduler clock for last write time in page * @ctx_offset: Signed offset from page to the logging context. Used to * optimize ram-dump extraction. * * @list: Linked list of pages that make up a log * @nd_read_offset: Non-destructive read offset used for debugfs * * The first part of the structure defines data that is used to extract the * logs from a memory dump and elements in this section should not be changed * or re-ordered. New local data structures can be added to the end of the * structure since they will be ignored by the extraction tool. */ struct ipc_log_page_header { uint32_t magic; uint32_t nmagic; uint32_t page_num; uint16_t read_offset; uint16_t write_offset; uint64_t log_id; uint64_t start_time; uint64_t end_time; int64_t ctx_offset; /* add local data structures after this point */ struct list_head list; uint16_t nd_read_offset; }; /** * struct ipc_log_page - Individual log page * * @hdr: Log page header * @data: Log data * * Each log consists of 1 to N log pages. Data size is adjusted to always fit * the structure into a single kernel page. */ struct ipc_log_page { struct ipc_log_page_header hdr; char data[PAGE_SIZE - sizeof(struct ipc_log_page_header)]; }; /** * struct ipc_log_context - main logging context * * @magic: Magic number (used for log extraction) * @nmagic: Inverse of magic number (used for log extraction) * @version: IPC Logging version of log format * @user_version: Version number for user-defined messages * @header_size: Size of the log header which is used to determine the offset * of ipc_log_page::data * @log_id: Log ID (assigned when log is created) * @name: Name of the log used to uniquely identify the log during extraction * * @list: List of log contexts (struct ipc_log_context) * @page_list: List of log pages (struct ipc_log_page) * @first_page: First page in list of logging pages * @last_page: Last page in list of logging pages * @write_page: Current write page * @read_page: Current read page (for internal reads) * @nd_read_page: Current debugfs extraction page (non-destructive) * * @write_avail: Number of bytes available to write in all pages * @dent: Debugfs node for run-time log extraction * @dfunc_info_list: List of deserialization functions * @context_lock_lhb1: Lock for entire structure * @read_avail: Completed when new data is added to the log */ struct ipc_log_context { uint32_t magic; uint32_t nmagic; uint32_t version; uint16_t user_version; uint16_t header_size; uint64_t log_id; char name[IPC_LOG_MAX_CONTEXT_NAME_LEN]; /* add local data structures after this point */ struct list_head list; struct list_head page_list; struct ipc_log_page *first_page; struct ipc_log_page *last_page; struct ipc_log_page *write_page; struct ipc_log_page *read_page; struct ipc_log_page *nd_read_page; uint32_t write_avail; struct dentry *dent; struct list_head dfunc_info_list; spinlock_t context_lock_lhb1; struct completion read_avail; struct kref refcount; bool destroyed; }; struct dfunc_info { struct list_head list; int type; void (*dfunc)(struct encode_context *, struct decode_context *); }; enum { TSV_TYPE_INVALID, TSV_TYPE_TIMESTAMP, TSV_TYPE_POINTER, TSV_TYPE_INT32, TSV_TYPE_BYTE_ARRAY, TSV_TYPE_QTIMER, }; enum { OUTPUT_DEBUGFS, }; #define IPC_LOG_CONTEXT_MAGIC_NUM 0x25874452 #define IPC_LOGGING_MAGIC_NUM 0x52784425 #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define IS_MSG_TYPE(x) (((x) > TSV_TYPE_MSG_START) && \ ((x) < TSV_TYPE_MSG_END)) #define MAX_MSG_DECODED_SIZE (MAX_MSG_SIZE*4) void ipc_log_context_free(struct kref *kref); static inline void ipc_log_context_put(struct ipc_log_context *ilctxt) { kref_put(&ilctxt->refcount, ipc_log_context_free); } #if (defined(CONFIG_DEBUG_FS)) void check_and_create_debugfs(void); void create_ctx_debugfs(struct ipc_log_context *ctxt, const char *mod_name); #else void check_and_create_debugfs(void) { } void create_ctx_debugfs(struct ipc_log_context *ctxt, const char *mod_name) { } #endif #endif