blob: 4fb6bcfb33caa0fe743b63ad946d931ca42d4c13 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30#include "bcmos_system.h"
31#include "bcmolt_math.h"
32#include "bcmtr_debug.h"
33#include "bcmolt_msg.h"
34#include "bcmolt_debug_api_common.h"
35
36#define API_CFG_PROP_EXISTS(mask, prop) (((mask) & (1ULL << (prop))) != 0)
37
38static void bcmolt_debug_api_common_capture_stats_update(bcmolt_devid device, bcmolt_debug_api_db *db)
39{
40 bcmos_errno err;
41 bcmtr_capture_info info;
42
43 err = bcmtr_capture_info_get(device, &info);
44 BUG_ON(BCM_ERR_OK != err);
45
46 db->cfg.api_capture_stats.buffer_used_bytes = info.used;
47 db->cfg.api_capture_stats.events_recorded = info.msgs;
48 db->cfg.api_capture_stats.events_dropped = info.lost;
49 db->cfg.api_capture_stats.buffer_wrap_count = info.wa;
50
51 err = bcmtr_capture_size_get(device, &db->cfg.api_capture_stats.readable_bytes);
52 BUG_ON(BCM_ERR_OK != err);
53}
54
55static bcmos_errno bcmolt_debug_api_common_capture_init(bcmolt_devid device, bcmolt_debug_api_db *db)
56{
57 bcmos_errno err;
58 bcmtr_capture_parm cap_parm = {};
59
60 cap_parm.size = db->cfg.api_capture_cfg.buffer_size_bytes;
61 cap_parm.ptr = db->capture_buffer;
62 cap_parm.stop_on_full = db->cfg.api_capture_cfg.buffer_mode == BCMOLT_API_CAPTURE_BUFFER_MODE_OVERFLOW;
63 cap_parm.activate = BCMOS_FALSE;
64
65 err = bcmtr_capture_init(device, &cap_parm);
66 BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err);
67
68 bcmolt_debug_api_common_capture_stats_update(device, db);
69 return BCM_ERR_OK;
70}
71
72bcmos_errno bcmolt_debug_api_common_get(bcmolt_devid device, bcmolt_msg *msg, bcmolt_debug_api_db *db)
73{
74 if (API_CFG_PROP_EXISTS(msg->presence_mask, BCMOLT_DEBUG_CFG_ID_API_CAPTURE_BUFFER))
75 {
76 uint32_t to_read = 0;
77
78 if (bcmtr_capture_is_active(device))
79 {
80 return bcmolt_msg_err(
81 msg,
82 DEV_LOG_INVALID_ID,
83 BCM_ERR_STATE,
84 BCMOLT_DEBUG_CFG_ID_API_CAPTURE_BUFFER,
85 "Cannot read capture buffer while capture is in progress");
86 }
87
88 if (db->cfg.api_capture_buffer_read.offset < db->cfg.api_capture_stats.readable_bytes)
89 {
90 to_read = MIN(
91 db->cfg.api_capture_buffer.len,
92 db->cfg.api_capture_stats.readable_bytes - db->cfg.api_capture_buffer_read.offset);
93 }
94 if ((db->cfg.api_capture_buffer.val != NULL) && (db->cfg.api_capture_buffer.len > 0))
95 {
96 bcmtr_capture_read(
97 device,
98 db->cfg.api_capture_buffer.val,
99 db->cfg.api_capture_buffer_read.offset,
100 &to_read);
101 memset(db->cfg.api_capture_buffer.val + (db->cfg.api_capture_buffer.len - to_read), 0, to_read);
102 }
103 }
104
105 return BCM_ERR_OK;
106}
107
108debug_trans_handle *bcmolt_debug_api_common_cfg_trans_start(bcmolt_debug_api_db *db)
109{
110 debug_trans_handle *handle = bcmos_calloc(sizeof(*handle));
111 handle->old_db = *db;
112 handle->new_db = db;
113 return handle;
114}
115
116void bcmolt_debug_api_common_cfg_trans_fail(bcmolt_debug_api_db *db, debug_trans_handle *handle)
117{
118 if (handle->old_db.capture_buffer != handle->new_db->capture_buffer)
119 {
120 bcmos_free(handle->new_db->capture_buffer);
121 }
122 if (handle->old_db.cfg.api_capture_buffer.val != handle->new_db->cfg.api_capture_buffer.val)
123 {
124 bcmos_free(handle->new_db->cfg.api_capture_buffer.val);
125 }
126 *db = handle->old_db;
127 bcmos_free(handle);
128}
129
130void bcmolt_debug_api_common_cfg_trans_succeed(bcmolt_devid device, debug_trans_handle *handle)
131{
132 bcmos_errno err;
133
134 if (handle->old_db.capture_buffer != handle->new_db->capture_buffer)
135 {
136 bcmos_free(handle->old_db.capture_buffer);
137 bcmtr_capture_destroy(device);
138 err = bcmolt_debug_api_common_capture_init(device, handle->new_db);
139 if (BCM_ERR_OK != err) /* cfg_set should have validated that this won't fail */
140 {
141 BCMOS_TRACE_ERR("Capture init failed (%s)!\n", bcmos_strerror(err));
142 }
143 }
144 if (handle->old_db.cfg.api_capture_buffer.val != handle->new_db->cfg.api_capture_buffer.val)
145 {
146 bcmos_free(handle->old_db.cfg.api_capture_buffer.val);
147 }
148 bcmos_free(handle);
149}
150
151bcmos_errno bcmolt_debug_api_common_set(
152 bcmolt_devid device,
153 bcmolt_msg *msg,
154 const bcmolt_debug_cfg_data *data,
155 debug_trans_handle *handle,
156 bcmolt_api_capture_location local)
157{
158 if (API_CFG_PROP_EXISTS(msg->presence_mask, BCMOLT_DEBUG_CFG_ID_API_CAPTURE_CFG))
159 {
160 if (bcmtr_capture_is_active(device))
161 {
162 return bcmolt_msg_err(
163 msg,
164 DEV_LOG_INVALID_ID,
165 BCM_ERR_STATE,
166 BCMOLT_DEBUG_CFG_ID_API_CAPTURE_CFG,
167 "Cannot change capture configuration while capture is in progress");
168 }
169 handle->new_db->cfg.api_capture_cfg = data->api_capture_cfg;
170 }
171
172 if (API_CFG_PROP_EXISTS(msg->presence_mask, BCMOLT_DEBUG_CFG_ID_API_CAPTURE_BUFFER_READ))
173 {
174 handle->new_db->cfg.api_capture_buffer_read = data->api_capture_buffer_read;
175 }
176
177 /* Once all the properties are handled, we need to take care of a few things that could depend on multiple
178 properties */
179 if ((handle->new_db->cfg.api_capture_cfg.location == local) &&
180 /* If we just switched to the device ... */
181 ((handle->new_db->cfg.api_capture_cfg.location != handle->old_db.cfg.api_capture_cfg.location) ||
182 /* ... or either the buffer size ... */
183 (handle->new_db->cfg.api_capture_cfg.buffer_size_bytes !=
184 handle->old_db.cfg.api_capture_cfg.buffer_size_bytes) ||
185 /* ... or the buffer mode have changed */
186 (handle->new_db->cfg.api_capture_cfg.buffer_mode != handle->old_db.cfg.api_capture_cfg.buffer_mode)))
187 {
188 handle->new_db->capture_buffer = bcmos_alloc(handle->new_db->cfg.api_capture_cfg.buffer_size_bytes);
189 if (handle->new_db->capture_buffer == NULL)
190 {
191 return bcmolt_msg_err(
192 msg,
193 DEV_LOG_INVALID_ID,
194 BCM_ERR_NOMEM,
195 BCMOLT_DEBUG_CFG_ID_API_CAPTURE_BUFFER_READ,
196 "Failed to allocate new capture buffer");
197 }
198 }
199
200 if ((handle->new_db->cfg.api_capture_cfg.location == local) &&
201 /* If we just switched to the device ... */
202 ((handle->new_db->cfg.api_capture_cfg.location != handle->old_db.cfg.api_capture_cfg.location) ||
203 /* ... or the read size has changed */
204 (handle->old_db.cfg.api_capture_buffer_read.size != handle->new_db->cfg.api_capture_buffer_read.size)))
205 {
206 handle->new_db->cfg.api_capture_buffer.len = handle->new_db->cfg.api_capture_buffer_read.size;
207 if (handle->new_db->cfg.api_capture_buffer.len != 0)
208 {
209 handle->new_db->cfg.api_capture_buffer.val = bcmos_alloc(handle->new_db->cfg.api_capture_buffer_read.size);
210 if (handle->new_db->cfg.api_capture_buffer.val == NULL)
211 {
212 return bcmolt_msg_err(
213 msg,
214 DEV_LOG_INVALID_ID,
215 BCM_ERR_NOMEM,
216 BCMOLT_DEBUG_CFG_ID_API_CAPTURE_BUFFER_READ,
217 "Failed to allocate new read buffer");
218 }
219 }
220 else
221 {
222 handle->new_db->cfg.api_capture_buffer.val = NULL;
223 }
224 }
225
226 return BCM_ERR_OK;
227}
228
229bcmos_errno bcmolt_debug_api_common_oper_start_api_capture(bcmolt_devid device, bcmolt_msg *msg)
230{
231 bcmos_errno err;
232 bcmtr_cld_filter filter;
233
234 if (bcmtr_capture_is_active(device))
235 {
236 return bcmolt_msg_err(
237 msg,
238 DEV_LOG_INVALID_ID,
239 BCM_ERR_ALREADY,
240 BCMOLT_ERR_FIELD_NONE,
241 "Capture already in progress");
242 }
243
244 /* capture everything */
245 filter.object = BCMOLT_OBJECT_ANY;
246 filter.group = BCMOLT_MGT_GROUP_ANY;
247 filter.subgroup = BCMOLT_SUBGROUP_ANY;
248 err = bcmtr_cld_level_set(device, &filter, BCMTR_CLD_CAPTURE);
249 BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err);
250 /* for now filter out start/stop operations and keep-alives */
251 filter.object = BCMOLT_OBJ_ID_DEBUG;
252 filter.group = BCMOLT_MGT_GROUP_OPER;
253 filter.subgroup = BCMOLT_DEBUG_OPER_ID_START_API_CAPTURE; /*lint !e633 */
254 err = bcmtr_cld_level_set(device, &filter, BCMTR_CLD_NONE);
255 BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err);
256 filter.subgroup = BCMOLT_DEBUG_OPER_ID_STOP_API_CAPTURE; /*lint !e633 */
257 err = bcmtr_cld_level_set(device, &filter, BCMTR_CLD_NONE);
258 BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err);
259 filter.object = BCMOLT_OBJ_ID_DEVICE;
260 filter.group = BCMOLT_MGT_GROUP_OPER;
261 filter.subgroup = BCMOLT_DEVICE_OPER_ID_HOST_KEEP_ALIVE; /*lint !e633 */
262 err = bcmtr_cld_level_set(device, &filter, BCMTR_CLD_NONE);
263 BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err);
264 filter.group = BCMOLT_MGT_GROUP_AUTO;
265 filter.subgroup = BCMOLT_DEVICE_AUTO_ID_DEVICE_KEEP_ALIVE; /*lint !e633 */
266 err = bcmtr_cld_level_set(device, &filter, BCMTR_CLD_NONE);
267 BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err);
268
269 return bcmtr_capture_start_stop(device, BCMOS_TRUE);
270}
271
272bcmos_errno bcmolt_debug_api_common_oper_stop_api_capture(bcmolt_devid device, bcmolt_msg *msg, bcmolt_debug_api_db *db)
273{
274 bcmos_errno err;
275
276 if (!bcmtr_capture_is_active(device))
277 {
278 return bcmolt_msg_err(
279 msg,
280 DEV_LOG_INVALID_ID,
281 BCM_ERR_ALREADY,
282 BCMOLT_ERR_FIELD_NONE,
283 "No capture in progress");
284 }
285
286 err = bcmtr_capture_start_stop(device, BCMOS_FALSE);
287 BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err);
288
289 bcmolt_debug_api_common_capture_stats_update(device, db);
290
291 return BCM_ERR_OK;
292}
293
294bcmos_errno bcmolt_debug_api_common_oper_reset_api_capture(bcmolt_devid device, bcmolt_msg *msg, bcmolt_debug_api_db *db)
295{
296 bcmos_errno err;
297
298 if (bcmtr_capture_is_active(device))
299 {
300 return bcmolt_msg_err(
301 msg,
302 DEV_LOG_INVALID_ID,
303 BCM_ERR_STATE,
304 BCMOLT_ERR_FIELD_NONE,
305 "Cannot reset capture while capture is running");
306 }
307
308 bcmtr_capture_destroy(device);
309 err = bcmolt_debug_api_common_capture_init(device, db);
310
311 return err;
312}
313
314void bcmolt_debug_api_common_init(bcmolt_devid device, bcmolt_debug_api_db *db)
315{
316 bcmos_errno err;
317
318#if ENABLE_LOG
319 db->log_id = bcm_dev_log_id_register("mh_debug", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
320#endif
321
322 bcmolt_debug_cfg_data_set_default(&db->cfg, BCMOLT_PRESENCE_MASK_ALL);
323 db->capture_buffer = bcmos_alloc(db->cfg.api_capture_cfg.buffer_size_bytes);
324 err = bcmolt_debug_api_common_capture_init(device, db);
325 BUG_ON(BCM_ERR_OK != err);
326}
327