| /* |
| * EVENT_LOG system definitions |
| * |
| * Copyright 1999-2016, Broadcom Corporation |
| * All rights reserved, |
| * |
| * Redistribution and use in source and binary forms, with or without modification, |
| * are permitted provided that the following conditions are met: |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * This software is provided by the copyright holder "as is" and any express or |
| * implied warranties, including, but not limited to, the implied warranties of |
| * merchantability and fitness for a particular purpose are disclaimed. In no event |
| * shall copyright holder be liable for any direct, indirect, incidental, special, |
| * exemplary, or consequential damages (including, but not limited to, procurement |
| * of substitute goods or services; loss of use, data, or profits; or business |
| * interruption) however caused and on any theory of liability, whether in |
| * contract, strict liability, or tort (including negligence or otherwise) arising |
| * in any way out of the use of this software, even if advised of the possibility |
| * of such damage |
| * |
| * |
| * <<Broadcom-WL-IPTag/Open:>> |
| * |
| * $Id: event_log.h 591285 2015-10-07 11:56:29Z $ |
| */ |
| |
| #ifndef _EVENT_LOG_H_ |
| #define _EVENT_LOG_H_ |
| |
| #include <typedefs.h> |
| #include <proto/event_log_set.h> |
| #include <proto/event_log_tag.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 |
| |
| /* |
| * 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 timestamp; /* Timestamp at start of use */ |
| uint32 event_logs; |
| } event_log_block_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_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. |
| * |
| */ |
| |
| #ifndef EVENT_LOG_DUMPER |
| |
| #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_LOG_ON(tag) 0 |
| |
| #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 != 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 != 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)) |
| |
| |
| #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; |
| |
| #include <siutils.h> |
| |
| extern int event_log_init(si_t *sih); |
| extern int event_log_set_init(si_t *sih, int set_num, int size); |
| extern int event_log_set_expand(si_t *sih, int set_num, int size); |
| extern int event_log_set_shrink(si_t *sih, 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); |
| 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); |
| |
| #endif /* EVENT_LOG_DUMPER */ |
| |
| #endif /* EVENT_LOG_COMPILE */ |
| |
| #endif /* __ASSEMBLER__ */ |
| |
| #endif /* _EVENT_LOG_H */ |