openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

bsltrace.c (6781B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * Broadcom System Log Trace Buffer Sink
      8  */
      9 #include <soc/drv.h>
     10 #include <sal/core/libc.h>
     11 #include <sal/core/sync.h>
     12 #include <sal/core/alloc.h>
     13 #include <sal/appl/io.h>
     14 #include <appl/diag/bslsink.h>
     15 #include <appl/diag/bslenable.h>
     16 #include <shared/bsl.h>
     17 
     18 /*
     19  * BSL copies the trace string to the buffer in two steps.
     20  * First the prefix string is copied, then the log string.
     21  * So each trace string uses two trace buffer entries.
     22  * Using a short entry length and double the max entries.
     23  */
     24 #define MAX_NUM_TRACE_ENTRIES 1000
     25 #define MAX_TRACE_ENTRY_LEN 64
     26 
     27 typedef struct bsl_trace_buf_s {
     28     char        * buffer_start;
     29     int           buffer_size;
     30     int           cur_num_entries;
     31     int           max_num_entries;
     32     int           entry_length;
     33     char        * head;
     34     sal_mutex_t   lock;
     35 } bsl_trace_buf_t;
     36 
     37 static bsl_trace_buf_t trace;
     38 static bslsink_sink_t trace_sink;
     39 
     40 /*
     41  * Note that inserting trace messages during an interrupt is
     42  * only allowed in cases where the interrupt handling is done
     43  * at thread level.
     44  */
     45 STATIC int bsltrace_add(const char *format, va_list args)
     46 {
     47     int str_len = 0;
     48 
     49     /* Lock access to trace buf */
     50     sal_mutex_take(trace.lock, sal_mutex_FOREVER);
     51 
     52     /* Add string to head of trace buffer */
     53     str_len = sal_vsprintf(trace.head, format, args);
     54 
     55     if (str_len > trace.entry_length) {
     56         /* Handle Error */
     57     } else if (str_len < 0) {
     58         /* Handle Error */
     59     } else {
     60         /* Increment head*/
     61         trace.head = (char *)(trace.head) + trace.entry_length;
     62 
     63         /* Handle wrap */
     64         if (trace.head == (trace.buffer_start + trace.buffer_size) ) {
     65             trace.head = trace.buffer_start;
     66         }
     67 
     68         /* Count up to max number of entries until full,
     69            then simply overwrite the oldest */
     70         if (trace.cur_num_entries < trace.max_num_entries) {
     71             trace.cur_num_entries++;
     72         }
     73     }
     74 
     75     /* Unlock access to trace buf */
     76     sal_mutex_give(trace.lock);
     77 
     78     return str_len;
     79 }
     80 
     81 STATIC int
     82 bsltrace_vfprintf(void *file, const char *format, va_list args)
     83 {
     84     /* Need to print to circular trace buffer */
     85     return bsltrace_add(format, args);
     86 }
     87 
     88 STATIC int
     89 bsltrace_cleanup(bslsink_sink_t * sink)
     90 {
     91 
     92     /* Free allocated trace buffer */
     93     if (trace.buffer_start) {
     94         sal_free(trace.buffer_start);
     95     }
     96 
     97     return 0;
     98 }
     99 
    100 int bsltrace_clear(void)
    101 {
    102     if (!trace.lock) {
    103         cli_out("Trace Buffer Not Initialized\n");
    104         return 0;
    105     }
    106 
    107     /* Lock access to trace buf */
    108     sal_mutex_take(trace.lock, sal_mutex_FOREVER);
    109 
    110     trace.head = trace.buffer_start;
    111     trace.cur_num_entries = 0;
    112 
    113     /* Unlock access to trace buf */
    114     sal_mutex_give(trace.lock);
    115 
    116     return 0;
    117 }
    118 
    119 /* Print the last "entries" entries.
    120  * Print all entries if "entries" < 0
    121  */
    122 int bsltrace_print(int entries)
    123 {
    124     char * entry = NULL;
    125     int i, j;
    126 
    127     if (!trace.lock) {
    128         cli_out("Trace Buffer Not Initialized\n");
    129         return 0;
    130     }
    131 
    132     /* Lock access to trace buf */
    133     sal_mutex_take(trace.lock, sal_mutex_FOREVER);
    134 
    135     if (trace.cur_num_entries == 0) {
    136         cli_out("Empty Trace Buffer\n");
    137 
    138         /* Unlock access to trace buf */
    139         sal_mutex_give(trace.lock);
    140 
    141         return 0;
    142     } else if (trace.cur_num_entries < trace.max_num_entries) {
    143         entry = trace.buffer_start;
    144     }
    145     else {
    146         entry = trace.head;
    147     }
    148 
    149     /* Print trace oldest to newest */
    150     if ((entries < 0) ||
    151         (entries > (trace.cur_num_entries / 2))) {
    152         j = 0;
    153     } else {
    154         j = (trace.cur_num_entries - (entries * 2));
    155     }
    156 
    157     for (i = 0; i < trace.cur_num_entries; i++) {
    158         if (i >= j) {
    159             cli_out("%s", entry);
    160         }
    161         entry += trace.entry_length;
    162         if (entry == (trace.buffer_start + trace.buffer_size)) {
    163             entry = trace.buffer_start;
    164         }
    165     }
    166 
    167     /* Unlock access to trace buf */
    168     sal_mutex_give(trace.lock);
    169 
    170     return 0;
    171 }
    172 
    173 /* As each trace string uses two trace buffer entries,
    174  * Adjust the number of entries accordingly..
    175  */
    176 int bsltrace_config_set(int nentry, int size)
    177 {
    178     int n, sz;
    179  
    180     if (!trace.lock) {
    181         cli_out("Trace Buffer Not Initialized\n");
    182         return 0;
    183     }
    184 
    185     if ((trace.max_num_entries == (nentry * 2)) &&
    186         (trace.entry_length == size)) {
    187         /* No Changes */
    188         return 0;
    189     }
    190     n = (nentry > 0) ? (nentry * 2) : trace.max_num_entries;
    191     sz = (size > 0) ? size : trace.entry_length;
    192 
    193     /* Lock access to trace buf */
    194     sal_mutex_take(trace.lock, sal_mutex_FOREVER);
    195 
    196     sal_free(trace.buffer_start);
    197 
    198     trace.buffer_start =
    199         sal_alloc(sz * n, "bsltrace");
    200     trace.head = trace.buffer_start;
    201     trace.buffer_size = sz * n;
    202     trace.cur_num_entries = 0;
    203     trace.max_num_entries = n;
    204     trace.entry_length = sz;
    205 
    206     /* Unlock access to trace buf */
    207     sal_mutex_give(trace.lock);
    208 
    209     return 0;
    210 }
    211 
    212 int bsltrace_config_get(int *nentry, int *size)
    213 {
    214     *nentry = trace.max_num_entries / 2;
    215     *size = trace.entry_length;
    216     return trace.cur_num_entries / 2;
    217 }
    218 
    219 int
    220 bsltrace_init(void)
    221 {
    222 
    223     bslsink_sink_t *sink;
    224 
    225     if (!soc_property_get(0, "tracesink", 1)) {
    226         return 0;
    227     }
    228 
    229     /* Create mutex lock to protect buffer access */
    230     if (!trace.lock) {
    231         trace.lock = sal_mutex_create("trace_lock");
    232     }
    233 
    234     /* Alocate and initialize trace buffer */
    235     trace.buffer_start =
    236         sal_alloc(MAX_TRACE_ENTRY_LEN * MAX_NUM_TRACE_ENTRIES, "bsltrace");
    237 
    238     if (trace.buffer_start == NULL) {
    239         return 1;
    240     }
    241     sal_memset(trace.buffer_start,
    242                0,
    243                MAX_TRACE_ENTRY_LEN * MAX_NUM_TRACE_ENTRIES);
    244 
    245     /* Initialize the trace buffer management info */
    246     trace.head = trace.buffer_start;
    247     trace.buffer_size = MAX_TRACE_ENTRY_LEN * MAX_NUM_TRACE_ENTRIES;
    248     trace.cur_num_entries = 0;
    249     trace.max_num_entries = MAX_NUM_TRACE_ENTRIES;
    250     trace.entry_length = MAX_TRACE_ENTRY_LEN;
    251 
    252     /* Create and configure the trace sink */
    253     sink = &trace_sink;
    254     bslsink_sink_t_init(sink);
    255     sal_strncpy(sink->name, "trace", sizeof(sink->name));
    256     sink->vfprintf = bsltrace_vfprintf;
    257     sink->cleanup = bsltrace_cleanup;
    258     sink->enable_range.min = bslSeverityDebug;
    259     sink->enable_range.max = bslSeverityDebug;
    260 
    261     /* Configure the trace prefix */
    262     sal_strncpy(sink->prefix_format, "%u:%L%S%s (%P:%T):",
    263                 sizeof(sink->prefix_format));
    264     sink->prefix_range.min = bslSeverityDebug;
    265     sink->prefix_range.max = bslSeverityDebug;
    266 
    267     bslsink_sink_add(sink);
    268 
    269     return 0;
    270 }