blob: 45764cbe2fed478a34d4127d52a85a62bc6ae887 [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#define HOST_API_CAPTURE 0
31
32#include "bcmos_system.h"
33#include "bcmolt_api.h"
34#include "bcmolt_msg.h"
35#include "bcmolt_tr_mux.h"
36#if HOST_API_CAPTURE
37#include "bcmolt_debug_api_common.h"
38#endif
39#include "bcmolt_dev_ctrl.h"
40#include "bcmolt_debug_ctrl.h"
41
42#define API_CAPTURE_PROP_MASK\
43 ((1ULL << BCMOLT_DEBUG_CFG_ID_API_CAPTURE_CFG) |\
44 (1ULL << BCMOLT_DEBUG_CFG_ID_API_CAPTURE_STATS) |\
45 (1ULL << BCMOLT_DEBUG_CFG_ID_API_CAPTURE_BUFFER_READ) |\
46 (1ULL << BCMOLT_DEBUG_CFG_ID_API_CAPTURE_BUFFER))
47
48typedef struct
49{
50 bcmos_bool waiting_for_ack;
51 bcmolt_msg *last_message;
52 bcmos_timer ack_timeout;
53#if HOST_API_CAPTURE
54 bcmolt_debug_api_db db;
55 debug_trans_handle *handle;
56#endif
57} debug_ctrl_ctxt;
58
59static debug_ctrl_ctxt debug_ctrl[BCMTR_MAX_OLTS];
60
61static void send_to_host(bcmolt_devid device, bcmolt_msg *msg)
62{
63 msg->dir = BCMOLT_MSG_DIR_RESPONSE;
64 bcmtrmux_control_to_host(device, msg);
65 bcmolt_msg_free(msg);
66}
67
68static void send_to_device(bcmolt_devid device, bcmolt_msg *msg)
69{
70 debug_ctrl[device].waiting_for_ack = BCMOS_TRUE;
71 debug_ctrl[device].last_message = msg;
72 bcmtrmux_control_to_line(device, msg);
73 bcmos_timer_start(&debug_ctrl[device].ack_timeout, DEVICE_RESPONSE_TIMEOUT_LENGTH);
74}
75
76static bcmos_bool bcmolt_debug_ctrl_cfg_requires_connection(bcmolt_msg *msg, const bcmolt_debug_cfg_data *cfg)
77{
78 return (((msg->presence_mask & ~API_CAPTURE_PROP_MASK) != 0) || /* includes non-API capture elements, or ... */
79 (((msg->presence_mask & API_CAPTURE_PROP_MASK) != 0) && /* includes API captue elements and ... */
80 (cfg->api_capture_cfg.location == BCMOLT_API_CAPTURE_LOCATION_DEVICE))); /* capture location is device */
81}
82
83static void bcmolt_debug_ctrl_send_cfg_get_response(bcmolt_devid device, bcmolt_msg *msg)
84{
85#if HOST_API_CAPTURE
86 if (debug_ctrl[device].db.cfg.api_capture_cfg.location == BCMOLT_API_CAPTURE_LOCATION_HOST)
87 {
88 bcmolt_debug_api_common_get(device, msg, &debug_ctrl[device].db);
89 }
90#endif
91 send_to_host(device, msg);
92}
93
94static void bcmolt_debug_ctrl_handle_cfg_get(bcmolt_devid device, bcmolt_msg *msg, bcmos_bool connected)
95{
96#if HOST_API_CAPTURE
97 if (bcmolt_debug_ctrl_cfg_requires_connection(msg, &debug_ctrl[device].db.cfg))
98#endif
99 {
100 if (connected)
101 {
102 send_to_device(device, msg);
103 return;
104 }
105
106 bcmolt_msg_err(
107 msg,
108 DEV_LOG_INVALID_ID,
109 BCM_ERR_NOT_CONNECTED,
110 BCMOLT_ERR_FIELD_NONE,
111 "Cannot access embedded parameters while disconnected");
112 }
113
114 bcmolt_debug_ctrl_send_cfg_get_response(device, msg);
115}
116
117static void bcmolt_debug_ctrl_send_cfg_set_response(bcmolt_devid device, bcmolt_msg *msg)
118{
119#if HOST_API_CAPTURE
120 if (msg->err == BCM_ERR_OK)
121 {
122 bcmolt_debug_api_common_cfg_trans_succeed(device, debug_ctrl[device].handle);
123 }
124 else
125 {
126 bcmolt_debug_api_common_cfg_trans_fail(&debug_ctrl[device].db, debug_ctrl[device].handle);
127 }
128#endif
129
130 send_to_host(device, msg);
131}
132
133static void bcmolt_debug_ctrl_handle_cfg_set(bcmolt_devid device, bcmolt_msg *msg, bcmos_bool connected)
134{
135 bcmolt_debug_cfg *cfg = (bcmolt_debug_cfg*)msg;
136 bcmolt_debug_cfg_id prop_id;
137 bcmos_errno err;
138
139 if (!bcmolt_debug_cfg_data_bounds_check(&cfg->data, msg->presence_mask, &prop_id))
140 {
141 err = BCM_ERR_RANGE;
142 msg->err_field_idx = (uint16_t)prop_id;
143 send_to_host(device, msg);
144 return;
145 }
146
147#if HOST_API_CAPTURE
148 debug_ctrl[device].handle = bcmolt_debug_api_common_cfg_trans_start(&debug_ctrl[device].db);
149 err = bcmolt_debug_api_common_set(device, msg, &cfg->data, debug_ctrl[device].handle, BCMOLT_API_CAPTURE_LOCATION_HOST);
150#else
151 if (BCMOLT_CFG_PROP_IS_SET(cfg, debug, api_capture_cfg) &&
152 (cfg->data.api_capture_cfg.location == BCMOLT_API_CAPTURE_LOCATION_HOST))
153 {
154 err = bcmolt_msg_err(
155 msg,
156 DEV_LOG_INVALID_ID,
157 BCM_ERR_NOT_SUPPORTED,
158 BCMOLT_ERR_FIELD_NONE,
159 "Host API capture not supported yet");
160 }
161 else
162 {
163 err = BCM_ERR_OK;
164 }
165#endif
166 if (err == BCM_ERR_OK)
167 {
168 if (bcmolt_debug_ctrl_cfg_requires_connection(msg, &cfg->data))
169 {
170 if (connected)
171 {
172 send_to_device(device, msg);
173 return;
174 }
175
176 bcmolt_msg_err(
177 msg,
178 DEV_LOG_INVALID_ID,
179 BCM_ERR_NOT_CONNECTED,
180 BCMOLT_ERR_FIELD_NONE,
181 "Cannot access embedded parameters while disconnected");
182 }
183 }
184
185 bcmolt_debug_ctrl_send_cfg_set_response(device, msg);
186}
187
188static void bcmolt_debug_ctrl_handle_cfg_clear(bcmolt_devid device, bcmolt_msg *msg, bcmos_bool connected)
189{
190#if HOST_API_CAPTURE
191 bcmolt_debug_cfg *cfg = (bcmolt_debug_cfg*)msg;
192#endif
193 bcmos_errno err;
194
195 if (!connected)
196 {
197 bcmolt_msg_err(
198 msg,
199 DEV_LOG_INVALID_ID,
200 BCM_ERR_NOT_CONNECTED,
201 BCMOLT_ERR_FIELD_NONE,
202 "Cannot access embedded parameters while disconnected");
203 send_to_host(device, msg);
204 return;
205 }
206
207#if HOST_API_CAPTURE
208 debug_ctrl[device].handle = bcmolt_debug_api_common_cfg_trans_start(&debug_ctrl[device].db);
209 bcmolt_debug_cfg_data_set_default(&debug_ctrl[device].db.cfg, BCMOLT_PRESENCE_MASK_ALL);
210 msg->presence_mask = BCMOLT_PRESENCE_MASK_ALL;
211 err = bcmolt_debug_api_common_set(device, msg, &cfg->data, debug_ctrl[device].handle, BCMOLT_API_CAPTURE_LOCATION_HOST);
212#else
213 err = BCM_ERR_OK;
214#endif
215 if (err == BCM_ERR_OK)
216 {
217 send_to_device(device, msg);
218 }
219 else
220 {
221 bcmolt_debug_ctrl_send_cfg_set_response(device, msg);
222 }
223}
224
225static void bcmolt_debug_ctrl_handle_cfg(bcmolt_devid device, bcmolt_msg *msg, bcmos_bool connected)
226{
227 switch (msg->type)
228 {
229 case BCMOLT_MSG_TYPE_GET:
230 bcmolt_debug_ctrl_handle_cfg_get(device, msg, connected);
231 break;
232 case BCMOLT_MSG_TYPE_SET:
233 bcmolt_debug_ctrl_handle_cfg_set(device, msg, connected);
234 break;
235 case BCMOLT_MSG_TYPE_CLEAR:
236 bcmolt_debug_ctrl_handle_cfg_clear(device, msg, connected);
237 break;
238 default:
239 bcmolt_msg_err(
240 msg,
241 DEV_LOG_INVALID_ID,
242 BCM_ERR_NOT_SUPPORTED,
243 BCMOLT_ERR_FIELD_NONE,
244 "Unsupported message type (%u)",
245 msg->type);
246 send_to_host(device, msg);
247 break;
248 }
249}
250
251static void bcmolt_debug_ctrl_handle_oper(bcmolt_devid device, bcmolt_msg *msg, bcmos_bool connected)
252{
253#if HOST_API_CAPTURE
254 bcmos_bool host_api_capture =
255 (debug_ctrl[device].db.cfg.api_capture_cfg.location == BCMOLT_API_CAPTURE_LOCATION_HOST);
256
257 switch (msg->subgroup)
258 {
259 case BCMOLT_DEBUG_OPER_ID_START_API_CAPTURE:
260 if (host_api_capture)
261 {
262 msg->err = bcmolt_debug_api_common_oper_start_api_capture(device, msg);
263 send_to_host(device, msg);
264 return;
265 }
266 break;
267 case BCMOLT_DEBUG_OPER_ID_STOP_API_CAPTURE:
268 if (host_api_capture)
269 {
270 msg->err = bcmolt_debug_api_common_oper_stop_api_capture(device, msg, &debug_ctrl[device].db);
271 send_to_host(device, msg);
272 return;
273 }
274 break;
275 case BCMOLT_DEBUG_OPER_ID_RESET_API_CAPTURE:
276 if (host_api_capture)
277 {
278 msg->err = bcmolt_debug_api_common_oper_reset_api_capture(device, msg, &debug_ctrl[device].db);
279 send_to_host(device, msg);
280 return;
281 }
282 break;
283 default:
284 break;
285 }
286#endif
287
288 if (!connected)
289 {
290 bcmolt_msg_err(
291 msg,
292 DEV_LOG_INVALID_ID,
293 BCM_ERR_NOT_CONNECTED,
294 BCMOLT_ERR_FIELD_NONE,
295 "Cannot perform embedded operations while disconnected");
296 send_to_host(device, msg);
297 return;
298 }
299
300 send_to_device(device, msg);
301}
302
303static void bcmolt_debug_ctrl_handle_auto_cfg(bcmolt_devid device, bcmolt_msg *msg, bcmos_bool connected)
304{
305 if (!connected)
306 {
307 bcmolt_msg_err(
308 msg,
309 DEV_LOG_INVALID_ID,
310 BCM_ERR_NOT_CONNECTED,
311 BCMOLT_ERR_FIELD_NONE,
312 "Cannot access embedded parameters while disconnected");
313 send_to_host(device, msg);
314 return;
315 }
316
317 send_to_device(device, msg);
318}
319
320static void bcmolt_debug_ctrl_handle_request(bcmolt_devid device, bcmolt_msg *msg, bcmos_bool connected)
321{
322 if (debug_ctrl[device].waiting_for_ack)
323 {
324 bcmolt_msg_err(
325 msg,
326 DEV_LOG_INVALID_ID,
327 BCM_ERR_TOO_MANY_REQS,
328 BCMOLT_ERR_FIELD_NONE,
329 "Transaction in progress on debug object");
330 send_to_host(device, msg);
331 return;
332 }
333
334 switch (msg->group)
335 {
336 case BCMOLT_MGT_GROUP_CFG:
337 bcmolt_debug_ctrl_handle_cfg(device, msg, connected);
338 break;
339 case BCMOLT_MGT_GROUP_OPER:
340 bcmolt_debug_ctrl_handle_oper(device, msg, connected);
341 break;
342 case BCMOLT_MGT_GROUP_AUTO_CFG:
343 bcmolt_debug_ctrl_handle_auto_cfg(device, msg, connected);
344 break;
345 default:
346 bcmolt_msg_err(
347 msg,
348 DEV_LOG_INVALID_ID,
349 BCM_ERR_NOT_SUPPORTED,
350 BCMOLT_ERR_FIELD_NONE,
351 "Unsupported group (%u)",
352 msg->group);
353 send_to_host(device, msg);
354 break;
355 }
356}
357
358static void bcmolt_debug_ctrl_handle_response(bcmolt_devid device, bcmolt_msg *msg)
359{
360 if (!debug_ctrl[device].waiting_for_ack || (msg->corr_tag != debug_ctrl[device].last_message->corr_tag))
361 {
362 msg->subch = BCMTRMUX_CHANNEL_AUTO_PROXY;
363 send_to_host(device, msg);
364 return;
365 }
366
367 msg->subch = debug_ctrl[device].last_message->subch;
368 bcmos_timer_stop(&debug_ctrl[device].ack_timeout);
369 debug_ctrl[device].waiting_for_ack = BCMOS_FALSE;
370 bcmolt_msg_free(debug_ctrl[device].last_message);
371
372 if (msg->err != BCM_ERR_OK)
373 {
374 send_to_host(device, msg);
375 return;
376 }
377
378 switch (msg->group)
379 {
380 case BCMOLT_MGT_GROUP_CFG:
381 switch (msg->type)
382 {
383 case BCMOLT_MSG_TYPE_GET:
384 bcmolt_debug_ctrl_send_cfg_get_response(device, msg);
385 break;
386 case BCMOLT_MSG_TYPE_SET:
387 bcmolt_debug_ctrl_send_cfg_set_response(device, msg);
388 break;
389 case BCMOLT_MSG_TYPE_CLEAR:
390 bcmolt_debug_ctrl_send_cfg_set_response(device, msg);
391 break;
392 default:
393 BCMOS_TRACE_ERR("Got unexpected response type (%u) from embedded\n", msg->group);
394 send_to_host(device, msg);
395 break;
396 }
397 break;
398 case BCMOLT_MGT_GROUP_OPER:
399 case BCMOLT_MGT_GROUP_AUTO_CFG:
400 send_to_host(device, msg);
401 break;
402 default:
403 BCMOS_TRACE_ERR("Got unexpected response group (%u) from embedded\n", msg->group);
404 send_to_host(device, msg);
405 break;
406 }
407}
408
409static bcmos_timer_rc bcmolt_debug_ctrl_handle_ack_timeout(bcmos_timer *timer, long data)
410{
411 bcmolt_devid device = (bcmolt_devid)data;
412
413 if (debug_ctrl[device].last_message == NULL)
414 {
415 BCMOS_TRACE_ERR("Waiting with no message!\n");
416 return BCMOS_TIMER_OK;
417 }
418
419 bcmolt_msg_err(
420 debug_ctrl[device].last_message,
421 DEV_LOG_INVALID_ID,
422 BCM_ERR_INTERNAL,
423 BCMOLT_ERR_FIELD_NONE,
424 "Did not receive response from embedded");
425 send_to_host(device, debug_ctrl [device].last_message);
426
427 return BCMOS_TIMER_OK;
428}
429
430void bcmolt_debug_ctrl_process_msg(bcmolt_devid device, bcmolt_msg *msg, bcmos_bool connected)
431{
432 switch (msg->dir)
433 {
434 case BCMOLT_MSG_DIR_REQUEST:
435 bcmolt_debug_ctrl_handle_request(device, msg, connected);
436 break;
437 case BCMOLT_MSG_DIR_RESPONSE:
438 bcmolt_debug_ctrl_handle_response(device, msg);
439 break;
440 default:
441 BCMOS_TRACE_ERR("Unsupported direction: %u\n", msg->dir);
442 bcmolt_msg_free(msg);
443 break;
444 }
445}
446
447void bcmolt_debug_ctrl_init(void)
448{
449 bcmolt_devid i;
450
451 for (i = 0; i < BCMTR_MAX_OLTS; i++)
452 {
453 bcmos_timer_parm tp =
454 {
455 .name = "debug_ctrl_ack_timeout",
456 .owner = BCMOS_MODULE_ID_DEV_CTRL_DEV0 + i,
457 .periodic = BCMOS_FALSE,
458 .handler = bcmolt_debug_ctrl_handle_ack_timeout,
459 .data = (long)i,
460 .flags = BCMOS_TIMER_PARM_FLAGS_URGENT,
461 };
462
463 debug_ctrl[i].waiting_for_ack = BCMOS_FALSE;
464 bcmos_timer_create(&debug_ctrl[i].ack_timeout, &tp);
465#if HOST_API_CAPTURE
466 bcmolt_debug_api_common_init(i, &debug_ctrl[i].db);
467#endif
468 }
469}