389 lines
15 KiB
C
389 lines
15 KiB
C
|
/*
|
||
|
* EVENT_LOG system definitions
|
||
|
*
|
||
|
* Copyright (C) 1999-2017, Broadcom Corporation
|
||
|
*
|
||
|
* Unless you and Broadcom execute a separate written software license
|
||
|
* agreement governing use of this software, this software is licensed to you
|
||
|
* under the terms of the GNU General Public License version 2 (the "GPL"),
|
||
|
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
|
||
|
* following added to such license:
|
||
|
*
|
||
|
* As a special exception, the copyright holders of this software give you
|
||
|
* permission to link this software with independent modules, and to copy and
|
||
|
* distribute the resulting executable under terms of your choice, provided that
|
||
|
* you also meet, for each linked independent module, the terms and conditions of
|
||
|
* the license of that module. An independent module is a module which is not
|
||
|
* derived from this software. The special exception does not apply to any
|
||
|
* modifications of the software.
|
||
|
*
|
||
|
* Notwithstanding the above, under no circumstances may you combine this
|
||
|
* software in any way with any other Broadcom software provided under a license
|
||
|
* other than the GPL, without Broadcom's express prior written consent.
|
||
|
*
|
||
|
*
|
||
|
* <<Broadcom-WL-IPTag/Open:>>
|
||
|
*
|
||
|
* $Id: event_log.h 711908 2017-07-20 10:37:34Z $
|
||
|
*/
|
||
|
|
||
|
#ifndef _EVENT_LOG_H_
|
||
|
#define _EVENT_LOG_H_
|
||
|
|
||
|
#include <typedefs.h>
|
||
|
#include <event_log_set.h>
|
||
|
#include <event_log_tag.h>
|
||
|
#include <event_log_payload.h>
|
||
|
#include <osl_decl.h>
|
||
|
|
||
|
/* logstrs header */
|
||
|
#define LOGSTRS_MAGIC 0x4C4F4753
|
||
|
#define LOGSTRS_VERSION 0x1
|
||
|
|
||
|
/* We make sure that the block size will fit in a single packet
|
||
|
* (allowing for a bit of overhead on each packet
|
||
|
*/
|
||
|
#define EVENT_LOG_MAX_BLOCK_SIZE 1400
|
||
|
#define EVENT_LOG_WL_BLOCK_SIZE 0x200
|
||
|
#define EVENT_LOG_PSM_BLOCK_SIZE 0x200
|
||
|
#define EVENT_LOG_BUS_BLOCK_SIZE 0x200
|
||
|
#define EVENT_LOG_ERROR_BLOCK_SIZE 0x200
|
||
|
/* Maximum event log record payload size = 1024 bytes or 256 words. */
|
||
|
#define EVENT_LOG_MAX_RECORD_PAYLOAD_SIZE 256
|
||
|
|
||
|
/*
|
||
|
* There are multiple levels of objects define here:
|
||
|
* event_log_set - a set of buffers
|
||
|
* event log groups - every event log call is part of just one. All
|
||
|
* event log calls in a group are handled the
|
||
|
* same way. Each event log group is associated
|
||
|
* with an event log set or is off.
|
||
|
*/
|
||
|
|
||
|
#ifndef __ASSEMBLER__
|
||
|
|
||
|
/* On the external system where the dumper is we need to make sure
|
||
|
* that these types are the same size as they are on the ARM the
|
||
|
* produced them
|
||
|
*/
|
||
|
#ifdef EVENT_LOG_DUMPER
|
||
|
#define _EL_BLOCK_PTR uint32
|
||
|
#define _EL_TYPE_PTR uint32
|
||
|
#define _EL_SET_PTR uint32
|
||
|
#define _EL_TOP_PTR uint32
|
||
|
#else
|
||
|
#define _EL_BLOCK_PTR struct event_log_block *
|
||
|
#define _EL_TYPE_PTR uint32 *
|
||
|
#define _EL_SET_PTR struct event_log_set **
|
||
|
#define _EL_TOP_PTR struct event_log_top *
|
||
|
#endif /* EVENT_LOG_DUMPER */
|
||
|
|
||
|
/* Event log sets (a logical circurlar buffer) consist of one or more
|
||
|
* event_log_blocks. The blocks themselves form a logical circular
|
||
|
* list. The log entries are placed in each event_log_block until it
|
||
|
* is full. Logging continues with the next event_log_block in the
|
||
|
* event_set until the last event_log_block is reached and then
|
||
|
* logging starts over with the first event_log_block in the
|
||
|
* event_set.
|
||
|
*/
|
||
|
typedef struct event_log_block {
|
||
|
_EL_BLOCK_PTR next_block;
|
||
|
_EL_BLOCK_PTR prev_block;
|
||
|
_EL_TYPE_PTR end_ptr;
|
||
|
|
||
|
/* Start of packet sent for log tracing */
|
||
|
uint16 pktlen; /* Size of rest of block */
|
||
|
uint16 count; /* Logtrace counter */
|
||
|
uint32 extra_hdr_info; /* LSB: 6 bits set id. MSB 24 bits reserved */
|
||
|
uint32 event_logs;
|
||
|
} event_log_block_t;
|
||
|
#define EVENT_LOG_BLOCK_HDRLEN 8 /* pktlen 2 + count 2 + extra_hdr_info 4 */
|
||
|
#define NAN_EVENT_LOG_MIN_LENGTH 2 /* Minimum length of Nan event */
|
||
|
|
||
|
typedef enum {
|
||
|
SET_DESTINATION_INVALID = -1,
|
||
|
SET_DESTINATION_HOST = 0,
|
||
|
SET_DESTINATION_NONE = 1,
|
||
|
SET_DESTINATION_MAX
|
||
|
} event_log_set_destination_t;
|
||
|
|
||
|
/* There can be multiple event_sets with each logging a set of
|
||
|
* associated events (i.e, "fast" and "slow" events).
|
||
|
*/
|
||
|
typedef struct event_log_set {
|
||
|
_EL_BLOCK_PTR first_block; /* Pointer to first event_log block */
|
||
|
_EL_BLOCK_PTR last_block; /* Pointer to last event_log block */
|
||
|
_EL_BLOCK_PTR logtrace_block; /* next block traced */
|
||
|
_EL_BLOCK_PTR cur_block; /* Pointer to current event_log block */
|
||
|
_EL_TYPE_PTR cur_ptr; /* Current event_log pointer */
|
||
|
uint32 blockcount; /* Number of blocks */
|
||
|
uint16 logtrace_count; /* Last count for logtrace */
|
||
|
uint16 blockfill_count; /* Fill count for logtrace */
|
||
|
uint32 timestamp; /* Last timestamp event */
|
||
|
uint32 cyclecount; /* Cycles at last timestamp event */
|
||
|
event_log_set_destination_t destination;
|
||
|
uint16 size; /* same size for all buffers in one set */
|
||
|
} event_log_set_t;
|
||
|
|
||
|
/* Top data structure for access to everything else */
|
||
|
typedef struct event_log_top {
|
||
|
uint32 magic;
|
||
|
#define EVENT_LOG_TOP_MAGIC 0x474C8669 /* 'EVLG' */
|
||
|
uint32 version;
|
||
|
#define EVENT_LOG_VERSION 1
|
||
|
uint32 num_sets;
|
||
|
uint32 logstrs_size; /* Size of lognums + logstrs area */
|
||
|
uint32 timestamp; /* Last timestamp event */
|
||
|
uint32 cyclecount; /* Cycles at last timestamp event */
|
||
|
_EL_SET_PTR sets; /* Ptr to array of <num_sets> set ptrs */
|
||
|
} event_log_top_t;
|
||
|
|
||
|
/* Data structure of Keeping the Header from logstrs.bin */
|
||
|
typedef struct {
|
||
|
uint32 logstrs_size; /* Size of the file */
|
||
|
uint32 rom_lognums_offset; /* Offset to the ROM lognum */
|
||
|
uint32 ram_lognums_offset; /* Offset to the RAM lognum */
|
||
|
uint32 rom_logstrs_offset; /* Offset to the ROM logstr */
|
||
|
uint32 ram_logstrs_offset; /* Offset to the RAM logstr */
|
||
|
/* Keep version and magic last since "header" is appended to the end of logstrs file. */
|
||
|
uint32 version; /* Header version */
|
||
|
uint32 log_magic; /* MAGIC number for verification 'LOGS' */
|
||
|
} logstr_header_t;
|
||
|
|
||
|
/*
|
||
|
* Use the following macros for generating log events.
|
||
|
*
|
||
|
* The FAST versions check the enable of the tag before evaluating the arguments and calling the
|
||
|
* event_log function. This adds 5 instructions. The COMPACT versions evaluate the arguments
|
||
|
* and call the event_log function unconditionally. The event_log function will then skip logging
|
||
|
* if this tag is disabled.
|
||
|
*
|
||
|
* To support easy usage of existing debugging (e.g. msglevel) via macro re-definition there are
|
||
|
* two variants of these macros to help.
|
||
|
*
|
||
|
* First there are the CAST versions. The event_log function normally logs uint32 values or else
|
||
|
* they have to be cast to uint32. The CAST versions blindly cast for you so you don't have to edit
|
||
|
* any existing code.
|
||
|
*
|
||
|
* Second there are the PAREN_ARGS versions. These expect the logging format string and arguments
|
||
|
* to be enclosed in parentheses. This allows us to make the following mapping of an existing
|
||
|
* msglevel macro:
|
||
|
* #define WL_ERROR(args) EVENT_LOG_CAST_PAREN_ARGS(EVENT_LOG_TAG_WL_ERROR, args)
|
||
|
*
|
||
|
* The versions of the macros without FAST or COMPACT in their name are just synonyms for the
|
||
|
* COMPACT versions.
|
||
|
*
|
||
|
* You should use the COMPACT macro (or its synonym) in cases where there is some preceding logic
|
||
|
* that prevents the execution of the macro, e.g. WL_ERROR by definition rarely gets executed.
|
||
|
* Use the FAST macro in performance sensitive paths. The key concept here is that you should be
|
||
|
* assuming that your macro usage is compiled into ROM and can't be changed ... so choose wisely.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#if !defined(EVENT_LOG_DUMPER) && !defined(DHD_EFI)
|
||
|
|
||
|
#ifndef EVENT_LOG_COMPILE
|
||
|
|
||
|
/* Null define if no tracing */
|
||
|
#define EVENT_LOG(format, ...)
|
||
|
#define EVENT_LOG_FAST(tag, fmt, ...)
|
||
|
#define EVENT_LOG_COMPACT(tag, fmt, ...)
|
||
|
|
||
|
#define EVENT_LOG_CAST(tag, fmt, ...)
|
||
|
#define EVENT_LOG_FAST_CAST(tag, fmt, ...)
|
||
|
#define EVENT_LOG_COMPACT_CAST(tag, fmt, ...)
|
||
|
|
||
|
#define EVENT_LOG_CAST_PAREN_ARGS(tag, pargs)
|
||
|
#define EVENT_LOG_FAST_CAST_PAREN_ARGS(tag, pargs)
|
||
|
#define EVENT_LOG_COMPACT_CAST_PAREN_ARGS(tag, pargs)
|
||
|
|
||
|
#define EVENT_LOG_IS_ON(tag) 0
|
||
|
#define EVENT_LOG_IS_LOG_ON(tag) 0
|
||
|
|
||
|
#define EVENT_LOG_BUFFER(tag, buf, size)
|
||
|
|
||
|
#else /* EVENT_LOG_COMPILE */
|
||
|
|
||
|
/* The first few are special because they can be done more efficiently
|
||
|
* this way and they are the common case. Once there are too many
|
||
|
* parameters the code size starts to be an issue and a loop is better
|
||
|
*/
|
||
|
#define _EVENT_LOG0(tag, fmt_num) \
|
||
|
event_log0(tag, fmt_num)
|
||
|
#define _EVENT_LOG1(tag, fmt_num, t1) \
|
||
|
event_log1(tag, fmt_num, t1)
|
||
|
#define _EVENT_LOG2(tag, fmt_num, t1, t2) \
|
||
|
event_log2(tag, fmt_num, t1, t2)
|
||
|
#define _EVENT_LOG3(tag, fmt_num, t1, t2, t3) \
|
||
|
event_log3(tag, fmt_num, t1, t2, t3)
|
||
|
#define _EVENT_LOG4(tag, fmt_num, t1, t2, t3, t4) \
|
||
|
event_log4(tag, fmt_num, t1, t2, t3, t4)
|
||
|
|
||
|
/* The rest call the generic routine that takes a count */
|
||
|
#define _EVENT_LOG5(tag, fmt_num, ...) event_logn(5, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG6(tag, fmt_num, ...) event_logn(6, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG7(tag, fmt_num, ...) event_logn(7, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG8(tag, fmt_num, ...) event_logn(8, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG9(tag, fmt_num, ...) event_logn(9, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOGA(tag, fmt_num, ...) event_logn(10, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOGB(tag, fmt_num, ...) event_logn(11, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOGC(tag, fmt_num, ...) event_logn(12, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOGD(tag, fmt_num, ...) event_logn(13, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOGE(tag, fmt_num, ...) event_logn(14, tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOGF(tag, fmt_num, ...) event_logn(15, tag, fmt_num, __VA_ARGS__)
|
||
|
|
||
|
|
||
|
/* Casting low level macros */
|
||
|
#define _EVENT_LOG_CAST0(tag, fmt_num) \
|
||
|
event_log0(tag, fmt_num)
|
||
|
#define _EVENT_LOG_CAST1(tag, fmt_num, t1) \
|
||
|
event_log1(tag, fmt_num, (uint32)(t1))
|
||
|
#define _EVENT_LOG_CAST2(tag, fmt_num, t1, t2) \
|
||
|
event_log2(tag, fmt_num, (uint32)(t1), (uint32)(t2))
|
||
|
#define _EVENT_LOG_CAST3(tag, fmt_num, t1, t2, t3) \
|
||
|
event_log3(tag, fmt_num, (uint32)(t1), (uint32)(t2), (uint32)(t3))
|
||
|
#define _EVENT_LOG_CAST4(tag, fmt_num, t1, t2, t3, t4) \
|
||
|
event_log4(tag, fmt_num, (uint32)(t1), (uint32)(t2), (uint32)(t3), (uint32)(t4))
|
||
|
|
||
|
/* The rest call the generic routine that takes a count */
|
||
|
#define _EVENT_LOG_CAST5(tag, fmt_num, ...) _EVENT_LOG5(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CAST6(tag, fmt_num, ...) _EVENT_LOG6(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CAST7(tag, fmt_num, ...) _EVENT_LOG7(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CAST8(tag, fmt_num, ...) _EVENT_LOG8(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CAST9(tag, fmt_num, ...) _EVENT_LOG9(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CASTA(tag, fmt_num, ...) _EVENT_LOGA(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CASTB(tag, fmt_num, ...) _EVENT_LOGB(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CASTC(tag, fmt_num, ...) _EVENT_LOGC(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CASTD(tag, fmt_num, ...) _EVENT_LOGD(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CASTE(tag, fmt_num, ...) _EVENT_LOGE(tag, fmt_num, __VA_ARGS__)
|
||
|
#define _EVENT_LOG_CASTF(tag, fmt_num, ...) _EVENT_LOGF(tag, fmt_num, __VA_ARGS__)
|
||
|
|
||
|
/* Hack to make the proper routine call when variadic macros get
|
||
|
* passed. Note the max of 15 arguments. More than that can't be
|
||
|
* handled by the event_log entries anyways so best to catch it at compile
|
||
|
* time
|
||
|
*/
|
||
|
|
||
|
#define _EVENT_LOG_VA_NUM_ARGS(F, _1, _2, _3, _4, _5, _6, _7, _8, _9, \
|
||
|
_A, _B, _C, _D, _E, _F, N, ...) F ## N
|
||
|
|
||
|
/* cast = _EVENT_LOG for no casting
|
||
|
* cast = _EVENT_LOG_CAST for casting of fmt arguments to uint32.
|
||
|
* Only first 4 arguments are casted to uint32. event_logn() is called
|
||
|
* if more than 4 arguments are present. This function internally assumes
|
||
|
* all arguments are uint32
|
||
|
*/
|
||
|
#define _EVENT_LOG(cast, tag, fmt, ...) \
|
||
|
static char logstr[] __attribute__ ((section(".logstrs"))) = fmt; \
|
||
|
static uint32 fmtnum __attribute__ ((section(".lognums"))) = (uint32) &logstr; \
|
||
|
_EVENT_LOG_VA_NUM_ARGS(cast, ##__VA_ARGS__, \
|
||
|
F, E, D, C, B, A, 9, 8, \
|
||
|
7, 6, 5, 4, 3, 2, 1, 0) \
|
||
|
(tag, (int) &fmtnum , ## __VA_ARGS__)
|
||
|
|
||
|
|
||
|
#define EVENT_LOG_FAST(tag, fmt, ...) \
|
||
|
do { \
|
||
|
if (event_log_tag_sets != NULL) { \
|
||
|
uint8 tag_flag = *(event_log_tag_sets + tag); \
|
||
|
if ((tag_flag & ~EVENT_LOG_TAG_FLAG_SET_MASK) != 0) { \
|
||
|
_EVENT_LOG(_EVENT_LOG, tag, fmt , ## __VA_ARGS__); \
|
||
|
} \
|
||
|
} \
|
||
|
} while (0)
|
||
|
|
||
|
#define EVENT_LOG_COMPACT(tag, fmt, ...) \
|
||
|
do { \
|
||
|
_EVENT_LOG(_EVENT_LOG, tag, fmt , ## __VA_ARGS__); \
|
||
|
} while (0)
|
||
|
|
||
|
/* Event log macro with casting to uint32 of arguments */
|
||
|
#define EVENT_LOG_FAST_CAST(tag, fmt, ...) \
|
||
|
do { \
|
||
|
if (event_log_tag_sets != NULL) { \
|
||
|
uint8 tag_flag = *(event_log_tag_sets + tag); \
|
||
|
if ((tag_flag & ~EVENT_LOG_TAG_FLAG_SET_MASK) != 0) { \
|
||
|
_EVENT_LOG(_EVENT_LOG_CAST, tag, fmt , ## __VA_ARGS__); \
|
||
|
} \
|
||
|
} \
|
||
|
} while (0)
|
||
|
|
||
|
#define EVENT_LOG_COMPACT_CAST(tag, fmt, ...) \
|
||
|
do { \
|
||
|
_EVENT_LOG(_EVENT_LOG_CAST, tag, fmt , ## __VA_ARGS__); \
|
||
|
} while (0)
|
||
|
|
||
|
|
||
|
#define EVENT_LOG(tag, fmt, ...) EVENT_LOG_COMPACT(tag, fmt , ## __VA_ARGS__)
|
||
|
|
||
|
#define EVENT_LOG_CAST(tag, fmt, ...) EVENT_LOG_COMPACT_CAST(tag, fmt , ## __VA_ARGS__)
|
||
|
|
||
|
#define _EVENT_LOG_REMOVE_PAREN(...) __VA_ARGS__
|
||
|
#define EVENT_LOG_REMOVE_PAREN(args) _EVENT_LOG_REMOVE_PAREN args
|
||
|
|
||
|
#define EVENT_LOG_CAST_PAREN_ARGS(tag, pargs) \
|
||
|
EVENT_LOG_CAST(tag, EVENT_LOG_REMOVE_PAREN(pargs))
|
||
|
|
||
|
#define EVENT_LOG_FAST_CAST_PAREN_ARGS(tag, pargs) \
|
||
|
EVENT_LOG_FAST_CAST(tag, EVENT_LOG_REMOVE_PAREN(pargs))
|
||
|
|
||
|
#define EVENT_LOG_COMPACT_CAST_PAREN_ARGS(tag, pargs) \
|
||
|
EVENT_LOG_COMPACT_CAST(tag, EVENT_LOG_REMOVE_PAREN(pargs))
|
||
|
|
||
|
/* Minimal event logging. Event log internally calls event_logx()
|
||
|
* log return address in caller.
|
||
|
* Note that the if(0){..} below is to avoid compiler warnings
|
||
|
* due to unused variables caused by this macro
|
||
|
*/
|
||
|
#define EVENT_LOG_RA(tag, args) \
|
||
|
do { \
|
||
|
if (0) { \
|
||
|
EVENT_LOG_COMPACT_CAST_PAREN_ARGS(tag, args); \
|
||
|
} \
|
||
|
event_log_caller_return_address(tag); \
|
||
|
} while (0)
|
||
|
|
||
|
#define EVENT_LOG_IS_LOG_ON(tag) (*(event_log_tag_sets + (tag)) & EVENT_LOG_TAG_FLAG_LOG)
|
||
|
|
||
|
#define EVENT_DUMP event_log_buffer
|
||
|
|
||
|
extern uint8 *event_log_tag_sets;
|
||
|
|
||
|
extern int event_log_init(osl_t *osh);
|
||
|
extern int event_log_set_init(osl_t *osh, int set_num, int size);
|
||
|
extern int event_log_set_expand(osl_t *osh, int set_num, int size);
|
||
|
extern int event_log_set_shrink(osl_t *osh, int set_num, int size);
|
||
|
|
||
|
extern int event_log_tag_start(int tag, int set_num, int flags);
|
||
|
extern int event_log_tag_stop(int tag);
|
||
|
|
||
|
typedef void (*event_log_logtrace_trigger_fn_t)(void *ctx);
|
||
|
void event_log_set_logtrace_trigger_fn(event_log_logtrace_trigger_fn_t fn, void *ctx);
|
||
|
|
||
|
event_log_top_t *event_log_get_top(void);
|
||
|
|
||
|
extern int event_log_get(int set_num, int buflen, void *buf);
|
||
|
|
||
|
extern uint8 *event_log_next_logtrace(int set_num);
|
||
|
|
||
|
extern void event_log0(int tag, int fmtNum);
|
||
|
extern void event_log1(int tag, int fmtNum, uint32 t1);
|
||
|
extern void event_log2(int tag, int fmtNum, uint32 t1, uint32 t2);
|
||
|
extern void event_log3(int tag, int fmtNum, uint32 t1, uint32 t2, uint32 t3);
|
||
|
extern void event_log4(int tag, int fmtNum, uint32 t1, uint32 t2, uint32 t3, uint32 t4);
|
||
|
extern void event_logn(int num_args, int tag, int fmtNum, ...);
|
||
|
|
||
|
extern void event_log_time_sync(uint32 ms);
|
||
|
extern void event_log_buffer(int tag, uint8 *buf, int size);
|
||
|
extern void event_log_caller_return_address(int tag);
|
||
|
extern int event_log_set_destination_set(int set, event_log_set_destination_t dest);
|
||
|
extern event_log_set_destination_t event_log_set_destination_get(int set);
|
||
|
|
||
|
#endif /* EVENT_LOG_DUMPER */
|
||
|
|
||
|
#endif /* EVENT_LOG_COMPILE */
|
||
|
|
||
|
#endif /* __ASSEMBLER__ */
|
||
|
|
||
|
#endif /* _EVENT_LOG_H_ */
|