2 * Global ASSERT Logging
4 * Copyright (C) 2013, Broadcom Corporation
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 $
18 #include <bcmendian.h>
22 #include <bcm_assert_log.h>
25 #if !defined(NDIS) && !defined(linux)
26 #error "ASSERT LOG only supports NDIS and LINUX in HIGH driver"
30 #define MAX_ASSERT_NUM 32
32 struct bcm_assert_info
{
42 assert_record_t assert_table
[MAX_ASSERT_NUM
];
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)
52 #define ASSERT_INIT_LOCK(context) do { \
53 NdisAllocateSpinLock(&(context)->lock); \
54 (context)->gotspinlocks = TRUE; \
56 #define ASSERT_FREE_LOCK(context) do { \
57 if ((context)->gotspinlocks) { \
58 NdisFreeSpinLock(&(context)->lock); \
59 (context)->gotspinlocks = FALSE; \
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
;
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
);
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
));
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)
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
++;
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
);
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;
144 assert_record_t
*log_record
= &results
->logs
[0];
147 if (g_assert_hdl
->ref_cnt
== 0)
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
) {
160 last_idx
= MODINC(cur_idx
, MAX_ASSERT_NUM
);
161 num
= MAX_ASSERT_NUM
- 1;
164 num
= MIN(iobuf_allowed_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
);