shared ARM updates
[tomato.git] / release / src-rt-6.x.4708 / shared / bcm_assert_log.c
blob69dc3d289793acad904c573b6bf5fa53d1de47c6
1 /*
2 * Global ASSERT Logging
4 * Copyright (C) 2013, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
12 * $Id: bcm_assert_log.c 401759 2013-05-13 16:08:08Z $
15 #include <epivers.h>
16 #include <typedefs.h>
17 #include <bcmdefs.h>
18 #include <bcmendian.h>
19 #include <osl.h>
20 #include <bcmutils.h>
22 #include <bcm_assert_log.h>
24 #ifdef WLC_HIGH
25 #if !defined(NDIS) && !defined(linux)
26 #error "ASSERT LOG only supports NDIS and LINUX in HIGH driver"
27 #endif
28 #endif /* WLC_HIGH */
30 #define MAX_ASSERT_NUM 32
32 struct bcm_assert_info {
33 uint8 ref_cnt;
34 uint8 cur_idx;
35 uint32 seq_num;
36 #if defined(linux)
37 spinlock_t lock;
38 #elif defined(NDIS)
39 NDIS_SPIN_LOCK lock;
40 bool gotspinlocks;
41 #endif
42 assert_record_t assert_table[MAX_ASSERT_NUM];
45 #if defined(linux)
46 #define ASSERT_INIT_LOCK(context) spin_lock_init(&(context)->lock)
47 #define ASSERT_FREE_LOCK(context)
48 #define ASSERT_LOCK(context) spin_lock(&(context)->lock)
49 #define ASSERT_UNLOCK(context) spin_unlock(&(context)->lock)
51 #elif defined(NDIS)
52 #define ASSERT_INIT_LOCK(context) do { \
53 NdisAllocateSpinLock(&(context)->lock); \
54 (context)->gotspinlocks = TRUE; \
55 } while (0)
56 #define ASSERT_FREE_LOCK(context) do { \
57 if ((context)->gotspinlocks) { \
58 NdisFreeSpinLock(&(context)->lock); \
59 (context)->gotspinlocks = FALSE; \
60 } \
61 } while (0)
62 #define ASSERT_LOCK(context) NdisAcquireSpinLock(&(context)->lock)
63 #define ASSERT_UNLOCK(context) NdisReleaseSpinLock(&(context)->lock)
64 #endif /* defined(linux) */
67 /* Global assert info table: This table cannot be dynamically allocated, since ndis
68 * requires allocations to be bound to a driver instance, so this table will have to
69 * be bound to a specific driver instance. This causes memory leaks in multiple
70 * instance scenario depending on order of load/unload. Hence, using a static allocation.
72 bcm_assert_info_t g_assert_info;
75 void
76 BCMATTACHFN(bcm_assertlog_init)(void)
78 bcm_assert_info_t *g_assert_hdl = &g_assert_info;
80 if (g_assert_hdl->ref_cnt == 0)
81 ASSERT_INIT_LOCK(g_assert_hdl);
83 ASSERT_LOCK(g_assert_hdl);
84 g_assert_hdl->ref_cnt++;
85 ASSERT_UNLOCK(g_assert_hdl);
87 return;
90 void
91 BCMATTACHFN(bcm_assertlog_deinit)(void)
93 bcm_assert_info_t *g_assert_hdl = &g_assert_info;
95 if (g_assert_hdl->ref_cnt) {
96 ASSERT_LOCK(g_assert_hdl);
97 g_assert_hdl->ref_cnt--;
98 ASSERT_UNLOCK(g_assert_hdl);
101 if (g_assert_hdl->ref_cnt == 0) {
102 ASSERT_FREE_LOCK(g_assert_hdl);
103 memset(g_assert_hdl, 0, sizeof(bcm_assert_info_t));
106 return;
109 void
110 bcm_assert_log(char *str)
112 bcm_assert_info_t *g_assert_hdl = &g_assert_info;
113 assert_record_t *cur_record;
115 if (g_assert_hdl->ref_cnt == 0)
116 return;
118 ASSERT_LOCK(g_assert_hdl);
120 cur_record = &g_assert_hdl->assert_table[g_assert_hdl->cur_idx];
121 cur_record->time = OSL_SYSUPTIME();
122 cur_record->seq_num = g_assert_hdl->seq_num++;
123 if (str) {
124 memset(cur_record->str, 0, MAX_ASSRTSTR_LEN);
125 memcpy(cur_record->str, str, MAX_ASSRTSTR_LEN - 1);
128 g_assert_hdl->cur_idx = MODINC(g_assert_hdl->cur_idx, MAX_ASSERT_NUM);
130 ASSERT_UNLOCK(g_assert_hdl);
132 return;
136 bcm_assertlog_get(void *outbuf, int iobuf_len)
138 bcm_assert_info_t *g_assert_hdl = &g_assert_info;
139 assertlog_results_t *results = (assertlog_results_t *)outbuf;
140 int iobuf_allowed_num = 0;
141 uint8 num = 0;
142 uint8 last_idx;
143 uint8 cur_idx;
144 assert_record_t *log_record = &results->logs[0];
145 int i;
147 if (g_assert_hdl->ref_cnt == 0)
148 return -1;
150 ASSERT_LOCK(g_assert_hdl);
152 iobuf_allowed_num = IOBUF_ALLOWED_NUM_OF_LOGREC(assert_record_t, iobuf_len);
154 cur_idx = g_assert_hdl->cur_idx;
155 if (g_assert_hdl->seq_num < MAX_ASSERT_NUM) {
156 last_idx = 0;
157 num = cur_idx;
159 else {
160 last_idx = MODINC(cur_idx, MAX_ASSERT_NUM);
161 num = MAX_ASSERT_NUM - 1;
164 num = MIN(iobuf_allowed_num, num);
166 results->num = num;
167 results->version = ASSERTLOG_CUR_VER;
168 results->record_len = sizeof(assert_record_t);
170 for (i = 0; i < num; i++) {
171 memcpy(&log_record[i], &g_assert_hdl->assert_table[last_idx],
172 sizeof(assert_record_t));
173 last_idx = MODINC(last_idx, MAX_ASSERT_NUM);
176 ASSERT_UNLOCK(g_assert_hdl);
178 return 0;