blob: 2ddfa8dd4b5c0e5497bd95af44dc51fe8409dfb3 [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 <bcm_config.h>
32#include <bcmolt_msg.h>
33#include <bcmolt_tr_mux.h>
34#include <bcmolt_api.h>
35#include <bcmolt_model_types.h>
36#include <bcmolt_model_ids.h>
37#include <bcmolt_host_sw_version.h>
38#include <bcmolt_model_revision.h>
39#include "bcmolt_dev_ctrl.h"
40#include "bcmtr_pcie.h"
41#include "bcmolt_llpcie.h"
42#include "bcm_dev_log.h"
43#include "bcmolt_utils.h"
44#include "bcmolt_firmware_envelope.h"
45#include "bcmolt_msg_pack.h"
46#include "bcmolt_mh_utils.h"
47#include "bcmolt_debug_ctrl.h"
48
49static bcmolt_dev_ctrl_params dev_ctrl_params;
50static dev_ctrl_database dev_ctrl_db[BCMTR_MAX_OLTS];
51static uint8_t *image_buf[BCMTR_MAX_OLTS];
52static uint8_t *rd_image_buf[BCMTR_MAX_OLTS];
53
54#define BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, fmt, args...)\
55 do\
56 {\
57 if (BCM_ERR_OK != rc)\
58 {\
59 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "%s: "fmt, bcmos_strerror(rc), ## args);\
60 return rc;\
61 }\
62 } while (0)
63
64#ifndef IN_BAND
65static bcmos_timer_rc dev_ctrl_boot_seq_timer_handler(bcmos_timer *timer, long data);
66static bcmos_timer_rc dev_ctrl_ddr_test_timer_handler(bcmos_timer *timer, long data);
67#endif
68
69const char *bcm_str_device_state(bcmolt_device_state device_state)
70{
71 static const char *strings[] =
72 {
73 [BCMOLT_DEVICE_STATE_DISCONNECTED] = "DISCONNECTED",
74 [BCMOLT_DEVICE_STATE_CONNECTING] = "CONNECTING",
75 [BCMOLT_DEVICE_STATE_READY] = "READY",
76 [BCMOLT_DEVICE_STATE_WAITING_FOR_DEVICE] = "WAITING_FOR_DEVICE",
77 [BCMOLT_DEVICE_STATE__NUM_OF] = "UNKNOWN"
78 };
79 return strings[device_state > BCMOLT_DEVICE_STATE__NUM_OF ? BCMOLT_DEVICE_STATE__NUM_OF : device_state];
80}
81
82const char *bcm_str_device_event(dev_ctrl_event device_event)
83{
84 static const char *strings[] =
85 {
86 [DEVICE_CONTROL_EVENT_DEVICE_CLEAR] = "DEVICE_CLEAR",
87 [DEVICE_CONTROL_EVENT_DEVICE_CONFIG_SET] = "DEVICE_CONFIG_SET",
88 [DEVICE_CONTROL_EVENT_DEVICE_CONFIG_GET] = "DEVICE_CONFIG_GET",
89 [DEVICE_CONTROL_EVENT_DEVICE_DISCONNECT] = "DEVICE_DISCONNECT",
90 [DEVICE_CONTROL_EVENT_DEVICE_TIMER_TIMEOUT] = "TIMER_TIMEOUT",
91 [DEVICE_CONTROL_EVENT_DEVICE_RECEIVED_ACK] = "RECEIVED_ACK",
92 [DEVICE_CONTROL_EVENT_DEVICE_CONNECT] = "DEVICE_CONNECT",
93 [DEVICE_CONTROL_EVENT_DEVICE_RESET] = "DEVICE_RESET",
94 [DEVICE_CONTROL_EVENT_CONNECTION_FAILURE] = "CONNECTION_FAILURE",
95 [DEVICE_CONTROL_EVENT_CONNECTION_ESTABLISHED] = "CONNECTION_ESTABLISHED",
96 [DEVICE_CONTROL_EVENT_DEVICE_READY] = "DEVICE_READY",
97 [DEVICE_CONTROL_EVENT_RUN_DDR_TEST] = "RUN_DDR_TEST",
98 [DEVICE_CONTROL_EVENT_DDR_TEST_COMPLETED] = "DDR_TEST_COMPLETED",
99 [DEVICE_CONTROL_EVENT_DDR_TEST_TIMEOUT] = "DDR_TEST_TIMEOUT",
100 [DEVICE_CONTROL_EVENT__NUM_OF] = "UNKNOWN"
101 };
102 return strings[device_event > DEVICE_CONTROL_EVENT__NUM_OF ? DEVICE_CONTROL_EVENT__NUM_OF : device_event];
103}
104
105#ifdef ENABLE_LOG
106static const char *bcm_str_auto_id(bcmolt_device_auto_id auto_id)
107{
108 static const char *strings[] =
109 {
110 [BCMOLT_DEVICE_AUTO_ID_DEVICE_READY] = "DEVICE_READY",
111 [BCMOLT_DEVICE_AUTO_ID_CONNECTION_ESTABLISHED] = "CONNECTION_ESTABLISHED",
112 [BCMOLT_DEVICE_AUTO_ID_DEVICE_KEEP_ALIVE] = "DEVICE_KEEP_ALIVE",
113 [BCMOLT_DEVICE_AUTO_ID_CONNECTION_FAILURE] = "CONNECTION_FAILURE",
114 [BCMOLT_DEVICE_AUTO_ID_CONNECTION_COMPLETE] = "CONNECTION_COMPLETE",
115 [BCMOLT_DEVICE_AUTO_ID_DISCONNECTION_COMPLETE] = "DISCONNECTION_COMPLETE",
116 [BCMOLT_DEVICE_AUTO_ID_SW_ERROR] = "SW_ERROR",
117 [BCMOLT_DEVICE_AUTO_ID__NUM_OF] = "UNKNOWN"
118 };
119 return strings[auto_id > BCMOLT_DEVICE_AUTO_ID__NUM_OF ? BCMOLT_DEVICE_AUTO_ID__NUM_OF : auto_id];
120}
121#endif
122
123const char *bcm_str_host_connection_fail_reason(bcmolt_host_connection_fail_reason reason)
124{
125 static const char *strings[] =
126 {
127 [BCMOLT_HOST_CONNECTION_FAIL_REASON_TIMEOUT] = "TIMEOUT",
128 [BCMOLT_HOST_CONNECTION_FAIL_REASON_KEEPALIVE] = "KEEPALIVE",
129 [BCMOLT_HOST_CONNECTION_FAIL_REASON_USER_CALLBACK_ERROR] = "USER_CALLBACK_ERROR",
130 [BCMOLT_HOST_CONNECTION_FAIL_REASON_SOFTWARE_VERSION_MISMATCH] = "SOFTWARE_VERSION_MISMATCH",
131 [BCMOLT_HOST_CONNECTION_FAIL_REASON_SYSTEM_MODE_MISMATCH] = "SYSTEM_MODE_MISMATCH",
132 [BCMOLT_HOST_CONNECTION_FAIL_REASON_NNI_SPEED_MISMATCH] = "NNI_SPEED_MISMATCH",
133 [BCMOLT_HOST_CONNECTION_FAIL_REASON_RECONNECT_TIMEOUT] = "RECONNECT_TIMEOUT",
134 [BCMOLT_HOST_CONNECTION_FAIL_REASON_INTERNAL_ERROR] = "INTERNAL_ERROR",
135 [BCMOLT_HOST_CONNECTION_FAIL_REASON_SYSTEM_MODE_NOT_SUPPORTED] = "SYSTEM_MODE_NOT_SUPPORTED",
136 [BCMOLT_HOST_CONNECTION_FAIL_REASON_PARAMETER] = "PARAMETER",
137 [BCMOLT_HOST_CONNECTION_FAIL_REASON__NUM_OF] = "UNKNOWN"
138 };
139 return strings[
140 reason > BCMOLT_HOST_CONNECTION_FAIL_REASON__NUM_OF ? BCMOLT_HOST_CONNECTION_FAIL_REASON__NUM_OF : reason];
141}
142
143const char *bcm_str_host_connecting_state(dev_ctrl_connecting_state state)
144{
145 static const char *strings[] =
146 {
147 [DEV_CTRL_CONNECTING_STATE_ESTABLISHING] = "ESTABLISHING",
148 [DEV_CTRL_CONNECTING_STATE_CONFIGURING] = "CONFIGURING",
149 [DEV_CTRL_CONNECTING_STATE_STANDALONE] = "STANDALONE"
150 };
151 return (state > DEV_CTRL_CONNECTING_STATE_STANDALONE) ? "UNKNOWN" : strings[state];
152}
153
154static inline bcmos_bool dev_ctrl_is_connected(bcmolt_device_state state)
155{
156 return (state == BCMOLT_DEVICE_STATE_READY || state == BCMOLT_DEVICE_STATE_WAITING_FOR_DEVICE);
157}
158
159void dev_ctrl_read_db(bcmolt_devid device, dev_ctrl_database *db)
160{
161 *db = dev_ctrl_db[device];
162}
163
164#ifndef IN_BAND
165#ifdef ENABLE_LOG
166static bcmos_errno dev_ctrl_get_dev_log(bcmolt_devid device, bcmolt_logger_cfg *msg)
167{
168 char *log_buf;
169 char *log_buf_copy;
170 int log_len;
171 int msg_len;
172 int i;
173 bcmos_errno rc;
174 bcm_dev_log_file log_file;
175 uint32_t msg_buf_offset;
176
177 if (msg->key.file_id != BCMOLT_LOG_FILE_ID_SRAM)
178 {
179 return bcmolt_msg_err(
180 &msg->hdr.hdr,
181 DEV_LOG_INVALID_ID,
182 BCM_ERR_KEY_RANGE,
183 BCMOLT_LOGGER_KEY_ID_FILE_ID,
184 "While disconnected, only the SRAM logger may be read");
185 }
186
187 if (BCMOLT_CFG_PROP_IS_SET(msg, logger, wrap_around))
188 {
189 return bcmolt_msg_err(
190 &msg->hdr.hdr,
191 DEV_LOG_INVALID_ID,
192 BCM_ERR_RANGE,
193 BCMOLT_LOGGER_CFG_ID_WRAP_AROUND,
194 "wrap_around cannot be retrieved while disconnected");
195 }
196
197 if (BCMOLT_CFG_PROP_IS_SET(msg, logger, enable_log))
198 {
199 return bcmolt_msg_err(
200 &msg->hdr.hdr,
201 DEV_LOG_INVALID_ID,
202 BCM_ERR_RANGE,
203 BCMOLT_LOGGER_CFG_ID_ENABLE_LOG,
204 "enable_log cannot be retrieved while disconnected");
205 }
206
207 if (BCMOLT_CFG_PROP_IS_SET(msg, logger, log_names))
208 {
209 return bcmolt_msg_err(
210 &msg->hdr.hdr,
211 DEV_LOG_INVALID_ID,
212 BCM_ERR_RANGE,
213 BCMOLT_LOGGER_CFG_ID_LOG_NAMES,
214 "log_names cannot be retrieved while disconnected");
215 }
216
217 if (!BCMOLT_CFG_PROP_IS_SET(msg, logger, buffer))
218 {
219 return BCM_ERR_OK; /* nothing to do */
220 }
221
222 if (dev_ctrl_db[device].fld_info.soc_sram_base == 0)
223 {
224 return bcmolt_msg_err(
225 &msg->hdr.hdr,
226 DEV_LOG_INVALID_ID,
227 BCM_ERR_STATE,
228 BCMOLT_LOGGER_CFG_ID_BUFFER,
229 "log buffer can only be retreived after initial device connection");
230 }
231
232 rc = bcm_fld_get_logs(device, &log_buf, &log_len);
233 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_fld_get_logs\n");
234
235 if (!log_len)
236 return BCM_ERR_OK;
237
238 /* Make a copy to avoid working over PCIe. Otherwise, the behavior can be unpredictable
239 * based on PCIe transaction size and controller configuration */
240 log_buf_copy = bcmos_alloc(log_len);
241 if (!log_buf_copy)
242 return BCM_ERR_NOMEM;
243
244 /* Copy byte by byte. Slow but works for any PCIe configuration */
245 for (i = 0; i < log_len; i++)
246 log_buf_copy[i] = log_buf[i];
247
248 msg->hdr.hdr.presence_mask |= (1 << BCMOLT_LOGGER_CFG_ID_BUFFER);
249
250 /* Attach log file to the buffer and read from the file */
251 rc = bcm_dev_log_file_attach(log_buf_copy, log_len, &log_file);
252
253 if (rc != BCM_ERR_OK || bcm_dev_log_get_num_of_messages(&log_file) == 0)
254 {
255 bcmos_free(log_buf_copy);
256 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "SRAM log buffer is empty\n");
257 return BCM_ERR_OK;
258 }
259
260 /* copy all messages from SRAM to the API message buffer (stopping when buffer is full) */
261 msg_buf_offset = 0;
262 do
263 {
264 msg_len = bcm_dev_log_file_read(&log_file, &dev_ctrl_db[device].sram_log_offset,
265 &msg->data.buffer.buff[msg_buf_offset], sizeof(msg->data.buffer.buff)- msg_buf_offset - 1);
266 if (msg_len <= 0)
267 break;
268 ++dev_ctrl_db[device].msgs_read;
269 /* The last character is 0-terminator. Take it out */
270 msg_buf_offset += msg_len - 1;
271 } while (msg_buf_offset < sizeof(msg->data.buffer.buff) - 1);
272
273 /* terminate the string with a null character */
274 msg->data.buffer.buff[msg_buf_offset] = '\0';
275 if (msg_len == BCM_ERR_OVERFLOW)
276 {
277 /* More records to read */
278 msg->data.buffer.msg_to_read = bcm_dev_log_get_num_of_messages(&log_file) - dev_ctrl_db[device].msgs_read;
279 }
280 else
281 {
282 /* all done */
283 msg->data.buffer.msg_to_read = 0;
284 dev_ctrl_db[device].sram_log_offset = 0;
285 dev_ctrl_db[device].msgs_read = 0;
286 }
287
288 /* Detach file from buffer */
289 bcm_dev_log_file_detach(&log_file);
290
291 bcmos_free(log_buf_copy);
292
293 return BCM_ERR_OK;
294}
295#endif
296
297static bcmos_errno dev_ctrl_get_sw_error_table(bcmolt_devid device)
298{
299 bcmos_sw_error_table *sw_error_table;
300 uint8_t *sram;
301 uint8_t *local;
302 uint32_t size;
303 uint32_t i;
304
305 sram = bcm_fld_get_sw_error_table(device, &size);
306 local = bcmos_alloc(size);
307 for (i = 0; i < size; i++)
308 {
309 local[i] = sram[i];
310 }
311
312 sw_error_table = (bcmos_sw_error_table*)local;
313 dev_ctrl_db[device].sw_error_count = BCMOS_ENDIAN_LITTLE_TO_CPU_U32(sw_error_table->count);
314 if (dev_ctrl_db[device].sw_error_count > NUM_ELEM(dev_ctrl_db[device].sw_errors))
315 {
316 bcmos_free(local);
317 return BCM_ERR_OVERFLOW;
318 }
319
320 for (i = 0; i < dev_ctrl_db[device].sw_error_count; i++)
321 {
322 dev_ctrl_db[device].sw_errors[i].first_error_time_us =
323 BCMOS_ENDIAN_LITTLE_TO_CPU_U64(sw_error_table->error[i].first_error_time);
324 dev_ctrl_db[device].sw_errors[i].last_error_time_us =
325 BCMOS_ENDIAN_LITTLE_TO_CPU_U64(sw_error_table->error[i].last_error_time);
326 dev_ctrl_db[device].sw_errors[i].line_number =
327 BCMOS_ENDIAN_LITTLE_TO_CPU_U32(sw_error_table->error[i].line_number);
328 dev_ctrl_db[device].sw_errors[i].error_counter =
329 BCMOS_ENDIAN_LITTLE_TO_CPU_U32(sw_error_table->error[i].error_counter);
330 dev_ctrl_db[device].sw_errors[i].instance =
331 BCMOS_ENDIAN_LITTLE_TO_CPU_U32(sw_error_table->error[i].instance);
332 strncpy(
333 dev_ctrl_db[device].sw_errors[i].filename,
334 sw_error_table->error[i].file_name,
335 BCMOLT_SW_ERROR_MAX_FILE_NAME_LEN);
336 dev_ctrl_db[device].sw_errors[i].filename[BCMOLT_SW_ERROR_MAX_FILE_NAME_LEN-1] = 0;
337 strncpy(
338 dev_ctrl_db[device].sw_errors[i].task_name,
339 sw_error_table->error[i].task_name,
340 BCMOLT_SW_ERROR_MAX_TASK_NAME_LEN);
341 dev_ctrl_db[device].sw_errors[i].task_name[BCMOLT_SW_ERROR_MAX_TASK_NAME_LEN-1] = 0;
342 }
343
344 bcmos_free(local);
345
346 return BCM_ERR_OK;
347}
348
349static bcmos_bool sw_error_key_valid(const bcmolt_software_error_key *key)
350{
351 bcmolt_devid device = (bcmolt_devid)bcmos_task_current()->parm.data;
352 return key->idx < dev_ctrl_db[device].sw_error_count;
353}
354
355static bcmos_errno mh_software_error_key_validate(bcmolt_msg *msg, const bcmolt_software_error_key *key)
356{
357 return sw_error_key_valid(key) ? BCM_ERR_OK : BCM_ERR_NOENT;
358}
359
360static bcmos_errno mh_software_error_cfg_get(
361 bcmolt_msg *msg,
362 const bcmolt_software_error_key *key,
363 bcmolt_software_error_cfg_data *data)
364{
365 bcmolt_devid device = (bcmolt_devid)bcmos_task_current()->parm.data;
366 bcmolt_presence_mask props = msg->presence_mask;
367 bcmos_errno rc = BCM_ERR_OK;
368
369 if (props == BCMOLT_PRESENCE_MASK_ALL)
370 {
371 /* Convert from sentinel "all" presence bits to set of all valid bits*/
372 props = (1U << BCMOLT_SOFTWARE_ERROR_CFG_ID__NUM_OF) - 1;
373 }
374
375 if (BCMOLT_CFG_PROP_IS_SET((bcmolt_software_error_cfg*)msg, software_error, entry))
376 {
377 if (dev_ctrl_db[device].fld_info.soc_sram_base == 0)
378 {
379 return bcmolt_msg_err(
380 msg,
381 DEV_LOG_INVALID_ID,
382 BCM_ERR_STATE,
383 BCMOLT_SOFTWARE_ERROR_CFG_ID_ENTRY,
384 "Software errors can only be retreived after initial device connection");
385 }
386
387 data->entry = dev_ctrl_db[device].sw_errors[key->idx];
388 props &= ~BCMOLT_PROP_MASK_GET(software_error, _cfg, entry);
389 }
390
391 if (props != 0)
392 {
393 rc = bcmolt_msg_err(msg,
394 DEV_LOG_INVALID_ID,
395 BCM_ERR_NOT_SUPPORTED,
396 BCMOLT_ERR_FIELD_NONE,
397 "Unsupported properties: 0x%llx", (unsigned long long)props);
398 }
399
400 return rc;
401}
402
403static bcmos_errno mh_software_error_key_iterate(bcmolt_software_error_key *key)
404{
405 key->idx++;
406 return sw_error_key_valid(key) ? BCM_ERR_OK : BCM_ERR_NO_MORE;
407}
408
409static bcmos_errno mh_software_error_key_resolve_wildcards(bcmolt_software_error_key *key)
410{
411 return BCM_ERR_OK;
412}
413
414MH_DECLARE_CFG_GET_MULTI(software_error)
415
416static bcmos_errno dev_ctrl_sw_error_get(bcmolt_devid device, bcmolt_msg *msg)
417{
418 bcmolt_software_error_cfg *cfg = (bcmolt_software_error_cfg*)msg;
419 bcmos_errno err = dev_ctrl_get_sw_error_table(device);
420 if (err != BCM_ERR_OK)
421 {
422 return BCM_ERR_INTERNAL;
423 }
424
425 if (msg->type == BCMOLT_MSG_TYPE_GET)
426 {
427 bcmolt_software_error_key_id key_prop_id;
428 if (!bcmolt_software_error_key_bounds_check(&cfg->key, BCMOLT_PRESENCE_MASK_ALL, &key_prop_id))
429 {
430 msg->err_field_idx = (uint16_t) key_prop_id;
431 return BCM_ERR_KEY_RANGE;
432 }
433
434 err = mh_software_error_key_validate(msg, &cfg->key);
435 if (err != BCM_ERR_OK)
436 {
437 return err;
438 }
439
440 return mh_software_error_cfg_get(msg, &cfg->key, &cfg->data);
441 }
442 else if (msg->type == BCMOLT_MSG_TYPE_GET_MULTI)
443 {
444 return mh_software_error_cfg_get_multi(cfg, msg->msg_set->filter_flags, msg->msg_set);
445 }
446 else
447 {
448 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Unexpected type 0x%x\n", msg->type);
449 }
450 return BCM_ERR_INTERNAL;
451}
452#endif
453
454static void dev_ctrl_send_indication(bcmolt_devid device, bcmolt_msg *msg)
455{
456 msg->subch = BCMTRMUX_CHANNEL_AUTO_PROXY;
457 msg->type = BCMOLT_MSG_TYPE_SET;
458 bcmtrmux_control_to_host(device, msg);
459}
460
461static void dev_ctrl_send_ind_connection_complete(bcmolt_devid device, bcmos_bool standalone)
462{
463 bcmolt_device_connection_complete ind = {};
464 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Connection complete: standalone=%s\n", standalone ? "yes" : "no");
465 BCMOLT_AUTO_INIT(&ind, device, connection_complete);
466 ind.data.standalone = standalone;
467 dev_ctrl_send_indication(device, &ind.hdr.hdr);
468}
469
470static void dev_ctrl_send_ind_disconnection_complete(bcmolt_devid device)
471{
472 bcmolt_device_disconnection_complete ind = {};
473 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Disconnection complete\n");
474 BCMOLT_AUTO_INIT(&ind, device, disconnection_complete);
475 dev_ctrl_send_indication(device, &ind.hdr.hdr);
476}
477
478static void dev_ctrl_send_ind_connection_failure(bcmolt_devid device, bcmolt_host_connection_fail_reason reason)
479{
480 bcmolt_device_connection_failure ind = {};
481 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Connection failure: %s\n", bcm_str_host_connection_fail_reason(reason));
482 BCMOLT_AUTO_INIT(&ind, device, connection_failure);
483 ind.data.reason = reason;
484 dev_ctrl_send_indication(device, &ind.hdr.hdr);
485 dev_ctrl_db[device].conn_fail_reason = reason; /* log the failure reason to the db. */
486}
487
488static void dev_ctrl_send_ind_connection_failure_from_msg(bcmolt_devid device, const bcmolt_msg *msg)
489{
490 BUG_ON(msg->subgroup != BCMOLT_DEVICE_AUTO_ID_CONNECTION_FAILURE);
491 dev_ctrl_send_ind_connection_failure(device, ((const bcmolt_device_connection_failure *)msg)->data.reason);
492}
493
494#ifndef IN_BAND
495static void dev_ctrl_send_ind_exception_log(bcmolt_devid device, uint32_t cpuid, const char *exception_buf)
496{
497 /* Because indication size is limited (but IND_MSG_MAX_SIZE > sizeof(bcmolt_str_2000.str), we may need to split into multiple indications.
498 * We use a static variable because our stack size is limited. */
499 static bcmolt_str_2000 api_exception_str;
500 const char *pos = exception_buf;
501 uint32_t remaining_len = strlen(pos);
502
503 while (remaining_len)
504 {
505 bcmolt_device_sw_exception ind = {};
506 uint32_t bytes_copied;
507
508 strncpy(api_exception_str.str, pos, sizeof(api_exception_str.str) - 1);
509 api_exception_str.str[sizeof(api_exception_str.str) - 1] = '\0';
510
511 BCMOLT_AUTO_INIT(&ind, device, sw_exception);
512 ind.data.cpu_id = cpuid;
513 ind.data.text = api_exception_str;
514 dev_ctrl_send_indication(device, &ind.hdr.hdr);
515
516 if (sizeof(api_exception_str.str) - 1 < remaining_len)
517 {
518 bytes_copied = sizeof(api_exception_str.str) - 1;
519 }
520 else
521 {
522 bytes_copied = remaining_len;
523 }
524 remaining_len -= bytes_copied;
525 pos += bytes_copied;
526 }
527}
528#endif
529
530static void dev_ctrl_send_config_set_msg(
531 bcmolt_devid device,
532 bcmolt_presence_mask mask,
533 uint16_t corr_tag,
534 const bcmolt_device_cfg_data *data)
535{
536 bcmolt_device_key key = {};
537 bcmolt_device_cfg cfg;
538 bcmos_errno rc;
539
540 BCMOLT_CFG_INIT(&cfg, device, key);
541 cfg.data = *data;
542 cfg.hdr.hdr.presence_mask = mask;
543
544 cfg.hdr.hdr.corr_tag = corr_tag;
545 cfg.hdr.hdr.type = BCMOLT_MSG_TYPE_SET;
546
547 rc = bcmtrmux_control_to_line(device, &cfg.hdr.hdr);
548 if (rc != BCM_ERR_OK)
549 {
550 BCM_LOG(ERROR, dev_ctrl_db[device].log_id,
551 "bcmtrmux_control_to_line of device config msg returned error %s (%d)\n",
552 bcmos_strerror(rc),
553 rc);
554 }
555}
556
557static void dev_ctrl_send_config_get_msg(bcmolt_devid device, bcmolt_presence_mask mask, uint16_t corr_tag)
558{
559 bcmolt_device_key key = {};
560 bcmolt_device_cfg cfg;
561 bcmos_errno rc;
562
563 BCMOLT_CFG_INIT(&cfg, device, key);
564 cfg.hdr.hdr.presence_mask = mask;
565
566 cfg.hdr.hdr.corr_tag = corr_tag;
567 cfg.hdr.hdr.type = BCMOLT_MSG_TYPE_GET;
568
569 rc = bcmtrmux_control_to_line(device, &cfg.hdr.hdr);
570 if (rc != BCM_ERR_OK)
571 {
572 BCM_LOG(ERROR, dev_ctrl_db[device].log_id,
573 "bcmtrmux_control_to_line of device config msg returned error %s (%d)\n",
574 bcmos_strerror(rc),
575 rc);
576 }
577}
578
579static void dev_ctrl_send_device_disconnect_msg(bcmolt_devid device, uint16_t corr_tag)
580{
581 bcmolt_device_key key = {};
582 bcmolt_device_disconnect oper;
583 bcmos_errno rc;
584
585 BCMOLT_OPER_INIT(&oper, device, disconnect, key);
586
587 oper.hdr.hdr.corr_tag = corr_tag;
588 oper.hdr.hdr.type = BCMOLT_MSG_TYPE_SET;
589 rc = bcmtrmux_control_to_line(device, &oper.hdr.hdr);
590 if (rc != BCM_ERR_OK)
591 {
592 BCM_LOG(ERROR, dev_ctrl_db[device].log_id,
593 "bcmtrmux_control_to_line of device disconnect operation returned error %s (%d)\n",
594 bcmos_strerror(rc),
595 rc);
596 }
597}
598
599/* Set all device object properties to default values. */
600static void dev_ctrl_clear_device_cfg(bcmolt_devid device)
601{
602 dev_ctrl_db[device].device_params_present = 0;
603
604 /* Pay attention: We use the interval and tolerance from dev_ctrl_db[device].ka_info and not from
605 * dev_ctrl_db[device].device_params. These parameters exist in dev_ctrl_db[device].device_params only because it is
606 * the data model representation. */
607 bcmolt_device_cfg_data_set_default(&dev_ctrl_db[device].device_params, BCMOLT_PRESENCE_MASK_ALL);
608 dev_ctrl_db[device].ka_info.ka_interval =
609 dev_ctrl_db[device].device_params.keepalive_interval * BCMOS_MICROSECONDS_IN_SECONDS;
610 dev_ctrl_db[device].ka_info.ka_tolerance = dev_ctrl_db[device].device_params.keepalive_tolerance;
611}
612
613static void dev_ctrl_init_connection_state(bcmolt_devid device)
614{
615 dev_ctrl_db[device].connection_info.config_send_counter = CONFIG_SEND_MAX_NUMBER;
616 dev_ctrl_db[device].connection_info.config_interval = DEVICE_CONTROL_CONFIG_TIME_US;
617}
618
619static bcmos_errno dev_ctrl_validate_cfg_set(bcmolt_devid device, bcmolt_msg *msg)
620{
621#ifndef IN_BAND
622 bcmos_errno rc;
623#endif
624 bcmolt_device_cfg *cfg = (bcmolt_device_cfg *)msg;
625 bcmolt_device_state state = dev_ctrl_db[device].device_params.state;
626 bcmolt_device_cfg_id failed_prop = BCMOLT_ERR_FIELD_NONE;
627
628 if (!bcmolt_device_cfg_data_bounds_check(&cfg->data, msg->presence_mask, &failed_prop))
629 {
630 msg->err_field_idx = (uint16_t)failed_prop;
631 return BCM_ERR_RANGE;
632 }
633
634#ifndef IN_BAND
635 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, system_mode))
636 {
637 if (state != BCMOLT_DEVICE_STATE_DISCONNECTED)
638 {
639 return bcmolt_msg_err(
640 msg,
641 DEV_LOG_INVALID_ID,
642 BCM_ERR_STATE,
643 BCMOLT_DEVICE_CFG_ID_SYSTEM_MODE,
644 "System mode can only be changed while disconnected");
645 }
646
647 rc = dev_ctrl_params.system_mode_validate_cb(device, cfg->data.system_mode);
648 if (rc != BCM_ERR_OK)
649 {
650 return bcmolt_msg_err(
651 msg,
652 DEV_LOG_INVALID_ID,
653 rc,
654 BCMOLT_DEVICE_CFG_ID_SYSTEM_MODE,
655 "Given system mode is not supported for this board");
656 }
657 }
658#endif
659
660 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, nni_speed) && state != BCMOLT_DEVICE_STATE_DISCONNECTED)
661 {
662 return bcmolt_msg_err(
663 msg,
664 DEV_LOG_INVALID_ID,
665 BCM_ERR_STATE,
666 BCMOLT_DEVICE_CFG_ID_NNI_SPEED,
667 "NNI speed can only be changed while disconnected");
668 }
669
670 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, debug) && state != BCMOLT_DEVICE_STATE_DISCONNECTED)
671 {
672 return bcmolt_msg_err(
673 msg,
674 DEV_LOG_INVALID_ID,
675 BCM_ERR_STATE,
676 BCMOLT_DEVICE_CFG_ID_DEBUG,
677 "Debug parameters can only be changed while disconnected");
678 }
679
680 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, firmware_sw_version) ||
681 BCMOLT_CFG_PROP_IS_SET(cfg, device, host_sw_version) ||
682 BCMOLT_CFG_PROP_IS_SET(cfg, device, chip_revision)||
683 BCMOLT_CFG_PROP_IS_SET(cfg, device, state)||
684 BCMOLT_CFG_PROP_IS_SET(cfg, device, chip_temperature)||
685 BCMOLT_CFG_PROP_IS_SET(cfg, device, chip_voltage))
686 {
687 return bcmolt_msg_err(
688 msg,
689 DEV_LOG_INVALID_ID,
690 BCM_ERR_STATE,
691 BCMOLT_ERR_FIELD_NONE,
692 "Cannot set read only fields");
693 }
694
695 return BCM_ERR_OK;
696}
697
698static bcmos_errno dev_ctrl_validate_cfg_get(bcmolt_devid device, bcmolt_msg *msg)
699{
700 bcmolt_device_state state = dev_ctrl_db[device].device_params.state;
701 bcmolt_device_cfg *cfg = (bcmolt_device_cfg *)msg;
702
703 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, firmware_sw_version) ||
704 BCMOLT_CFG_PROP_IS_SET(cfg, device, chip_revision) ||
705 BCMOLT_CFG_PROP_IS_SET(cfg, device, chip_temperature)||
706 BCMOLT_CFG_PROP_IS_SET(cfg, device, chip_voltage) ||
707 BCMOLT_CFG_PROP_IS_SET(cfg, device, epon_tod_string))
708 {
709 if (!dev_ctrl_is_connected(state))
710 {
711 return bcmolt_msg_err(
712 msg,
713 DEV_LOG_INVALID_ID,
714 BCM_ERR_STATE,
715 BCMOLT_ERR_FIELD_NONE,
716 "Cannot retrieve parameter while disconnected.");
717 }
718 }
719 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, protection_switching_ext_irq))
720 {
721 if (!dev_ctrl_is_connected(state) &&
722 (dev_ctrl_db[device].device_params_present &
723 BCMOLT_PROP_MASK_GET(device, _cfg, protection_switching_ext_irq)) == 0)
724 {
725 return bcmolt_msg_err(
726 msg,
727 DEV_LOG_INVALID_ID,
728 BCM_ERR_STATE,
729 BCMOLT_DEVICE_CFG_ID_PROTECTION_SWITCHING_EXT_IRQ,
730 "Cannot retrieve protection_switching_ext_irq while disconnected and not having a cache.");
731 }
732 }
733 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, epon_clock_transport_sample_delay))
734 {
735 if (!dev_ctrl_is_connected(state) &&
736 (dev_ctrl_db[device].device_params_present &
737 BCMOLT_PROP_MASK_GET(device, _cfg, epon_clock_transport_sample_delay)) == 0)
738 {
739 return bcmolt_msg_err(
740 msg,
741 DEV_LOG_INVALID_ID,
742 BCM_ERR_STATE,
743 BCMOLT_DEVICE_CFG_ID_EPON_CLOCK_TRANSPORT_SAMPLE_DELAY,
744 "Cannot retrieve epon_clock_transport_sample_delay while disconnected and not having a cache.");
745 }
746 }
747 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, indication_shaping))
748 {
749 if (!dev_ctrl_is_connected(state) &&
750 (dev_ctrl_db[device].device_params_present & BCMOLT_PROP_MASK_GET(device, _cfg, indication_shaping)) == 0)
751 {
752 return bcmolt_msg_err(
753 msg,
754 DEV_LOG_INVALID_ID,
755 BCM_ERR_STATE,
756 BCMOLT_DEVICE_CFG_ID_INDICATION_SHAPING,
757 "Cannot retrieve indication_shaping while disconnected and not having a cache.");
758 }
759 }
760 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, gpon_xgpon_tod_enable))
761 {
762 if (!dev_ctrl_is_connected(state) &&
763 (dev_ctrl_db[device].device_params_present &
764 BCMOLT_PROP_MASK_GET(device, _cfg, gpon_xgpon_tod_enable)) == 0)
765 {
766 return bcmolt_msg_err(
767 msg,
768 DEV_LOG_INVALID_ID,
769 BCM_ERR_STATE,
770 BCMOLT_DEVICE_CFG_ID_GPON_XGPON_TOD_ENABLE,
771 "Cannot retrieve gpon_xgpon_tod_enable while disconnected and not having a cache.");
772 }
773 }
774 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, gpon_xgpon_tod_gpio_pin))
775 {
776 if (!dev_ctrl_is_connected(state) &&
777 (dev_ctrl_db[device].device_params_present &
778 BCMOLT_PROP_MASK_GET(device, _cfg, gpon_xgpon_tod_gpio_pin)) == 0)
779 {
780 return bcmolt_msg_err(
781 msg,
782 DEV_LOG_INVALID_ID,
783 BCM_ERR_STATE,
784 BCMOLT_DEVICE_CFG_ID_GPON_XGPON_TOD_GPIO_PIN,
785 "Cannot retrieve gpon_xgpon_tod_gpio_pin while disconnected and not having a cache.");
786 }
787 }
788 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, gpon_xgpon_tod_connected_internally))
789 {
790 if (!dev_ctrl_is_connected(state) &&
791 (dev_ctrl_db[device].device_params_present &
792 BCMOLT_PROP_MASK_GET(device, _cfg, gpon_xgpon_tod_connected_internally)) == 0)
793 {
794 return bcmolt_msg_err(
795 msg,
796 DEV_LOG_INVALID_ID,
797 BCM_ERR_STATE,
798 BCMOLT_DEVICE_CFG_ID_GPON_XGPON_TOD_CONNECTED_INTERNALLY,
799 "Cannot retrieve gpon_xgpon_tod_connected_internally while disconnected and not having a cache.");
800 }
801 }
802 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, epon_8021_as_tod_format))
803 {
804 if (!dev_ctrl_is_connected(state) &&
805 (dev_ctrl_db[device].device_params_present &
806 BCMOLT_PROP_MASK_GET(device, _cfg, epon_8021_as_tod_format)) == 0)
807 {
808 return bcmolt_msg_err(
809 msg,
810 DEV_LOG_INVALID_ID,
811 BCM_ERR_STATE,
812 BCMOLT_DEVICE_CFG_ID_EPON_8021_AS_TOD_FORMAT,
813 "Cannot retrieve epon_8021_as_tod_format while disconnected and not having a cache.");
814 }
815 }
816 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, epon_shaper_mode))
817 {
818 if (!dev_ctrl_is_connected(state) &&
819 (dev_ctrl_db[device].device_params_present &
820 BCMOLT_PROP_MASK_GET(device, _cfg, epon_shaper_mode)) == 0)
821 {
822 return bcmolt_msg_err(
823 msg,
824 DEV_LOG_INVALID_ID,
825 BCM_ERR_STATE,
826 BCMOLT_DEVICE_CFG_ID_EPON_SHAPER_MODE,
827 "Cannot retrieve epon_shaper_mode while disconnected and not having a cache.");
828 }
829 }
830 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, embedded_image_list))
831 {
832 if (!dev_ctrl_is_connected(state) &&
833 (dev_ctrl_db[device].device_params_present &
834 BCMOLT_PROP_MASK_GET(device, _cfg, embedded_image_list)) == 0)
835 {
836 return bcmolt_msg_err(
837 msg,
838 DEV_LOG_INVALID_ID,
839 BCM_ERR_STATE,
840 BCMOLT_DEVICE_CFG_ID_EMBEDDED_IMAGE_LIST,
841 "Cannot retrieve embedded_image_list while disconnected and not having a cache.");
842 }
843 }
844 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, gpon_xgpon_tod_string_length))
845 {
846 if (!dev_ctrl_is_connected(state) &&
847 (dev_ctrl_db[device].device_params_present &
848 BCMOLT_PROP_MASK_GET(device, _cfg, gpon_xgpon_tod_string_length)) == 0)
849 {
850 return bcmolt_msg_err(
851 msg,
852 DEV_LOG_INVALID_ID,
853 BCM_ERR_STATE,
854 BCMOLT_DEVICE_CFG_ID_GPON_XGPON_TOD_STRING_LENGTH,
855 "Cannot retrieve gpon_xgpon_tod_string_length while disconnected and not having a cache.");
856 }
857 }
858 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, tod_uart_baudrate))
859 {
860 if (!dev_ctrl_is_connected(state) &&
861 (dev_ctrl_db[device].device_params_present &
862 BCMOLT_PROP_MASK_GET(device, _cfg, tod_uart_baudrate)) == 0)
863 {
864 return bcmolt_msg_err(
865 msg,
866 DEV_LOG_INVALID_ID,
867 BCM_ERR_STATE,
868 BCMOLT_DEVICE_CFG_ID_TOD_UART_BAUDRATE,
869 "Cannot retrieve tod_uart_baudrate while disconnected and not having a cache.");
870 }
871 }
872 return BCM_ERR_OK;
873}
874
875static bcmos_errno dev_ctrl_validate_cfg_clear(bcmolt_devid device, bcmolt_msg *msg)
876{
877 if (dev_ctrl_db[device].device_params.state != BCMOLT_DEVICE_STATE_DISCONNECTED)
878 {
879 return bcmolt_msg_err(
880 msg,
881 DEV_LOG_INVALID_ID,
882 BCM_ERR_STATE,
883 BCMOLT_ERR_FIELD_NONE,
884 "Device cfg_clear is only allowed while disconnected");
885 }
886 return BCM_ERR_OK;
887}
888
889static bcmos_errno bcm_dev_ctrl_validate_oper_connect(bcmolt_devid device, bcmolt_msg *msg)
890{
891 bcmolt_device_state state = dev_ctrl_db[device].device_params.state;
892
893 if (dev_ctrl_is_connected(state))
894 {
895 return bcmolt_msg_err(msg, DEV_LOG_INVALID_ID, BCM_ERR_ALREADY, BCMOLT_ERR_FIELD_NONE, "already connected");
896 }
897
898 /* If not all mandatory properties are valid return "mandatory parameter is missing" */
899 if (dev_ctrl_db[device].device_params.system_mode >= BCMOLT_SYSTEM_MODE__NUM_OF)
900 {
901 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Cannot connect: system mode not included\n");
902 return bcmolt_msg_err(
903 msg,
904 DEV_LOG_INVALID_ID,
905 BCM_ERR_MANDATORY_PARM_IS_MISSING,
906 BCMOLT_DEVICE_CFG_ID_SYSTEM_MODE,
907 "System mode must be set before connecting");
908 }
909#ifdef IN_BAND
910 /* For In Band Management IP Address and UDP port must be set prior to connecting*/
911 /* If not all mandatory properties are valid return "mandatory parameter is missing" */
912 if (dev_ctrl_db[device].device_params.device_ip_address.u32 == 0)
913 {
914 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Cannot connect: must set IP Address port\n");
915 return bcmolt_msg_err(
916 msg,
917 DEV_LOG_INVALID_ID,
918 BCM_ERR_MANDATORY_PARM_IS_MISSING,
919 BCMOLT_DEVICE_CFG_ID_DEVICE_IP_ADDRESS,
920 "Device IP Address must be set before connecting");
921 }
922 if (dev_ctrl_db[device].device_params.device_udp_port == 0)
923 {
924 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Cannot connect: must set IP Address UDP port\n");
925 return bcmolt_msg_err(
926 msg,
927 DEV_LOG_INVALID_ID,
928 BCM_ERR_MANDATORY_PARM_IS_MISSING,
929 BCMOLT_DEVICE_CFG_ID_DEVICE_UDP_PORT,
930 "UDP port must be set before connecting");
931 }
932#endif
933
934 return BCM_ERR_OK;
935}
936
937static bcmos_errno bcm_dev_ctrl_validate_oper_disconnect(bcmolt_devid device, bcmolt_msg *msg)
938{
939 bcmolt_device_state state = dev_ctrl_db[device].device_params.state;
940 if (state == BCMOLT_DEVICE_STATE_DISCONNECTED)
941 {
942 return bcmolt_msg_err(msg, DEV_LOG_INVALID_ID, BCM_ERR_ALREADY, BCMOLT_ERR_FIELD_NONE, "already disconnected");
943 }
944 return BCM_ERR_OK;
945}
946
947static bcmos_errno bcm_dev_ctrl_validate_oper_run_ddr_test(bcmolt_devid device, bcmolt_msg *msg)
948{
949 bcmolt_device_run_ddr_test *ddr_test = (bcmolt_device_run_ddr_test*)msg;
950 bcmos_bool is_standalone;
951 bcmos_errno rc;
952
953 if (BCMOLT_DEVICE_STATE_DISCONNECTED != dev_ctrl_db[device].device_params.state)
954 {
955 return bcmolt_msg_err(
956 msg,
957 DEV_LOG_INVALID_ID,
958 BCM_ERR_STATE,
959 BCMOLT_ERR_FIELD_NONE,
960 "DDR test can only be run when disconnected");
961 }
962
963 if (dev_ctrl_db[device].is_host_reset_pending)
964 {
965 return bcmolt_msg_err(
966 msg,
967 DEV_LOG_INVALID_ID,
968 BCM_ERR_STATE,
969 BCMOLT_ERR_FIELD_NONE,
970 "Cannot run DDR test while host reset is pending");
971 }
972
973 /* Check if the chip is running in standalone mode */
974 rc = dev_ctrl_params.device_is_running_cb(device, &is_standalone);
975 if (rc != BCM_ERR_OK)
976 {
977 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "device_is_running_cb returned error: %s (%d)\n", bcmos_strerror(rc), rc);
978 return bcmolt_msg_err(
979 msg,
980 DEV_LOG_INVALID_ID,
981 rc,
982 BCMOLT_ERR_FIELD_NONE,
983 "Failed to retrieve device status");
984 }
985 if (is_standalone)
986 {
987 return bcmolt_msg_err(
988 msg,
989 DEV_LOG_INVALID_ID,
990 BCM_ERR_STATE,
991 BCMOLT_ERR_FIELD_NONE,
992 "Cannot run DDR test while device is running");
993 }
994
995 if (!ddr_test->data.cpu && !ddr_test->data.ras_0 && !ddr_test->data.ras_1)
996 {
997 return bcmolt_msg_err(
998 msg,
999 DEV_LOG_INVALID_ID,
1000 BCM_ERR_STATE,
1001 BCMOLT_ERR_FIELD_NONE,
1002 "Must request at least one DDR Test");
1003 }
1004
1005 return BCM_ERR_OK;
1006}
1007
1008static bcmos_errno dev_ctrl_validate_operation(bcmolt_devid device, bcmolt_msg *msg)
1009{
1010 bcmolt_device_state state = dev_ctrl_db[device].device_params.state;
1011 if (state == BCMOLT_DEVICE_STATE_CONNECTING)
1012 {
1013 return bcmolt_msg_err(
1014 msg,
1015 DEV_LOG_INVALID_ID,
1016 BCM_ERR_STATE,
1017 BCMOLT_ERR_FIELD_NONE,
1018 "Device operations are not allowed while connecting");
1019 }
1020 if (state == BCMOLT_DEVICE_STATE_TESTING_DDR)
1021 {
1022 return bcmolt_msg_err(
1023 msg,
1024 DEV_LOG_INVALID_ID,
1025 BCM_ERR_STATE,
1026 BCMOLT_ERR_FIELD_NONE,
1027 "Device operations are not allowed while DDR test is in progress");
1028 }
1029
1030 switch (msg->subgroup)
1031 {
1032 case BCMOLT_DEVICE_OPER_ID_CONNECT:
1033 return bcm_dev_ctrl_validate_oper_connect(device, msg);
1034 case BCMOLT_DEVICE_OPER_ID_DISCONNECT:
1035 return bcm_dev_ctrl_validate_oper_disconnect(device, msg);
1036 case BCMOLT_DEVICE_OPER_ID_RUN_DDR_TEST:
1037 return bcm_dev_ctrl_validate_oper_run_ddr_test(device, msg);
1038 default:
1039 return BCM_ERR_OK;
1040 }
1041}
1042
1043static bcmos_errno dev_ctrl_validate_msg(bcmolt_devid device, bcmolt_msg *msg)
1044{
1045 if (dev_ctrl_db[device].device_params.state == BCMOLT_DEVICE_STATE_WAITING_FOR_DEVICE)
1046 {
1047 return bcmolt_msg_err(
1048 msg,
1049 DEV_LOG_INVALID_ID,
1050 BCM_ERR_STATE,
1051 BCMOLT_ERR_FIELD_NONE,
1052 "The device object is busy processing another API request");
1053 }
1054
1055 if (msg->group == BCMOLT_MGT_GROUP_CFG)
1056 {
1057 switch (msg->type)
1058 {
1059 case BCMOLT_MSG_TYPE_CLEAR:
1060 return dev_ctrl_validate_cfg_clear(device, msg);
1061 case BCMOLT_MSG_TYPE_SET:
1062 return dev_ctrl_validate_cfg_set(device, msg);
1063 case BCMOLT_MSG_TYPE_GET:
1064 return dev_ctrl_validate_cfg_get(device, msg);
1065 default:
1066 break;
1067 }
1068 }
1069
1070 if (msg->group == BCMOLT_MGT_GROUP_OPER && msg->type == BCMOLT_MSG_TYPE_SET)
1071 {
1072 return dev_ctrl_validate_operation(device, msg);
1073 }
1074
1075 return bcmolt_msg_err(
1076 msg,
1077 DEV_LOG_INVALID_ID,
1078 BCM_ERR_INTERNAL,
1079 BCMOLT_ERR_FIELD_NONE,
1080 "Invalid message for device control");
1081}
1082
1083static bcmolt_presence_mask dev_ctrl_fill_from_local(bcmolt_devid device)
1084{
1085 bcmolt_device_cfg *cfg = (bcmolt_device_cfg *)dev_ctrl_db[device].last_message;
1086 bcmolt_presence_mask mask = dev_ctrl_db[device].last_message->presence_mask;
1087
1088 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, system_mode))
1089 {
1090 cfg->data.system_mode = dev_ctrl_db[device].device_params.system_mode;
1091 mask &= ~BCMOLT_PROP_MASK_GET(device, _cfg, system_mode);
1092 }
1093
1094 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, keepalive_interval))
1095 {
1096 cfg->data.keepalive_interval = dev_ctrl_db[device].ka_info.ka_interval / BCMOS_MICROSECONDS_IN_SECONDS;
1097 mask &= ~BCMOLT_PROP_MASK_GET(device, _cfg, keepalive_interval);
1098 }
1099
1100 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, keepalive_tolerance))
1101 {
1102 cfg->data.keepalive_tolerance = dev_ctrl_db[device].ka_info.ka_tolerance;
1103 mask &= ~BCMOLT_PROP_MASK_GET(device, _cfg, keepalive_tolerance);
1104 }
1105
1106 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, host_sw_version))
1107 {
1108 cfg->data.host_sw_version.major = BCMOLT_HOST_MAJOR_VER;
1109 cfg->data.host_sw_version.minor = BCMOLT_HOST_MINOR_VER;
1110 cfg->data.host_sw_version.revision = BCMOLT_HOST_REVISION_VER;
1111 cfg->data.host_sw_version.model = BCMOLT_MODEL_REVISION;
1112 snprintf(
1113 cfg->data.host_sw_version.build_time,
1114 sizeof(cfg->data.host_sw_version.build_time),
1115 "%s %s",
1116 __DATE__,
1117 __TIME__);
1118 mask &= ~BCMOLT_PROP_MASK_GET(device, _cfg, host_sw_version);
1119 }
1120
1121 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, state))
1122 {
1123 cfg->data.state = dev_ctrl_db[device].device_params.state;
1124 mask &= ~BCMOLT_PROP_MASK_GET(device, _cfg, state);
1125 }
1126
1127 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, debug))
1128 {
1129 cfg->data.debug = dev_ctrl_db[device].device_params.debug;
1130 mask &= ~BCMOLT_PROP_MASK_GET(device, _cfg, debug);
1131 }
1132
1133 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, nni_speed))
1134 {
1135 cfg->data.nni_speed = dev_ctrl_db[device].device_params.nni_speed;
1136 mask &= ~BCMOLT_PROP_MASK_GET(device, _cfg, nni_speed);
1137 }
1138
1139 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, xgpon_num_of_onus))
1140 {
1141 cfg->data.xgpon_num_of_onus = dev_ctrl_db[device].device_params.xgpon_num_of_onus;
1142 mask &= ~BCMOLT_PROP_MASK_GET(device, _cfg, xgpon_num_of_onus);
1143 }
1144
1145 return mask;
1146}
1147
1148static void dev_ctrl_update_local_configuration(bcmolt_devid device, const bcmolt_msg *msg)
1149{
1150 const bcmolt_device_cfg *cfg = (const bcmolt_device_cfg *)msg;
1151
1152 dev_ctrl_db[device].device_params_present |= msg->presence_mask;
1153
1154 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, system_mode))
1155 {
1156 dev_ctrl_db[device].device_params.system_mode = cfg->data.system_mode;
1157 }
1158 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, debug))
1159 {
1160 dev_ctrl_db[device].device_params.debug = cfg->data.debug;
1161 }
1162 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, nni_speed))
1163 {
1164 dev_ctrl_db[device].device_params.nni_speed = cfg->data.nni_speed;
1165 }
1166 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, keepalive_interval))
1167 {
1168 dev_ctrl_db[device].ka_info.ka_interval = (cfg->data.keepalive_interval * BCMOS_MICROSECONDS_IN_SECONDS);
1169 dev_ctrl_db[device].device_params.keepalive_interval = cfg->data.keepalive_interval;
1170 }
1171 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, keepalive_tolerance))
1172 {
1173 dev_ctrl_db[device].ka_info.ka_tolerance = cfg->data.keepalive_tolerance;
1174 dev_ctrl_db[device].device_params.keepalive_tolerance = cfg->data.keepalive_tolerance;
1175 }
1176 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, protection_switching_ext_irq))
1177 {
1178 dev_ctrl_db[device].device_params.protection_switching_ext_irq = cfg->data.protection_switching_ext_irq;
1179 }
1180 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, epon_clock_transport_sample_delay))
1181 {
1182 dev_ctrl_db[device].device_params.epon_clock_transport_sample_delay =
1183 cfg->data.epon_clock_transport_sample_delay;
1184 }
1185 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, indication_shaping))
1186 {
1187 dev_ctrl_db[device].device_params.indication_shaping = cfg->data.indication_shaping;
1188 }
1189 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, gpon_xgpon_tod_enable))
1190 {
1191 dev_ctrl_db[device].device_params.gpon_xgpon_tod_enable = cfg->data.gpon_xgpon_tod_enable;
1192 }
1193 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, gpon_xgpon_tod_gpio_pin))
1194 {
1195 dev_ctrl_db[device].device_params.gpon_xgpon_tod_gpio_pin = cfg->data.gpon_xgpon_tod_gpio_pin;
1196 }
1197 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, gpon_xgpon_tod_connected_internally))
1198 {
1199 dev_ctrl_db[device].device_params.gpon_xgpon_tod_connected_internally = cfg->data.gpon_xgpon_tod_connected_internally;
1200 }
1201 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, epon_shaper_mode))
1202 {
1203 dev_ctrl_db[device].device_params.epon_shaper_mode = cfg->data.epon_shaper_mode;
1204 }
1205 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, embedded_image_list))
1206 {
1207 dev_ctrl_db[device].device_params.embedded_image_list = cfg->data.embedded_image_list;
1208 }
1209 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, xgpon_num_of_onus))
1210 {
1211 dev_ctrl_db[device].device_params.xgpon_num_of_onus = cfg->data.xgpon_num_of_onus;
1212 }
1213 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, device_ip_address))
1214 {
1215 dev_ctrl_db[device].device_params.device_ip_address = cfg->data.device_ip_address;
1216 }
1217 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, device_udp_port))
1218 {
1219 dev_ctrl_db[device].device_params.device_udp_port = cfg->data.device_udp_port;
1220 }
1221 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, gpon_xgpon_tod_string_length))
1222 {
1223 dev_ctrl_db[device].device_params.gpon_xgpon_tod_string_length = cfg->data.gpon_xgpon_tod_string_length;
1224 }
1225 if (BCMOLT_CFG_PROP_IS_SET(cfg, device, tod_uart_baudrate))
1226 {
1227 dev_ctrl_db[device].device_params.tod_uart_baudrate = cfg->data.tod_uart_baudrate;
1228 }
1229}
1230
1231static bcmos_errno dev_ctrl_validate_fw_version(bcmolt_devid device, const bcmolt_firmware_sw_version *version)
1232{
1233 BCM_LOG(INFO, dev_ctrl_db[device].log_id,
1234 "Firmware SW version %u.%u.%u (Object model revision %u, Build time: %s)\n",
1235 version->major,
1236 version->minor,
1237 version->revision,
1238 version->model,
1239 version->build_time);
1240
1241 BCM_LOG(INFO, dev_ctrl_db[device].log_id,
1242 "Host SW version %u.%u.%u (Object model revision %u, Build time: %s %s)\n",
1243 BCMOLT_HOST_MAJOR_VER,
1244 BCMOLT_HOST_MINOR_VER,
1245 BCMOLT_HOST_REVISION_VER,
1246 BCMOLT_MODEL_REVISION,
1247 __DATE__,
1248 __TIME__);
1249
1250 /* Version mismatch - note that only the Host/Firmware revisions can be different between the host and the firmware */
1251 if (version->major != BCMOLT_HOST_MAJOR_VER ||
1252 version->minor != BCMOLT_HOST_MINOR_VER ||
1253 version->model != BCMOLT_MODEL_REVISION)
1254 {
1255 BCM_LOG(INFO, dev_ctrl_db[device].log_id,
1256 "SW Versions Mismatch: Host SW version is %u.%u.%u with object model revision %d, while Firmware SW version is %u.%u.%u with object model revision %u\n",
1257 BCMOLT_HOST_MAJOR_VER,
1258 BCMOLT_HOST_MINOR_VER,
1259 BCMOLT_HOST_REVISION_VER,
1260 BCMOLT_MODEL_REVISION,
1261 version->major,
1262 version->minor,
1263 version->revision,
1264 version->model);
1265 return BCM_ERR_STATE;
1266 }
1267 return BCM_ERR_OK;
1268}
1269
1270#ifndef IN_BAND
1271static bcmos_errno dev_ctrl_register_fld(bcmolt_devid device)
1272{
1273 bcmos_errno rc;
1274 bcm_ll_dev_info ll_info;
1275
1276 if (dev_ctrl_db[device].fld_info.soc_sram_base > 0)
1277 {
1278 /* we have already queried the PCIe / registered with the FLD */
1279 return BCM_ERR_OK;
1280 }
1281
1282 rc = bcm_ll_pcie_query(device, &ll_info);
1283 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_ll_pcie_query\n");
1284 dev_ctrl_db[device].fld_info.soc_ddr_length = ll_info.soc_ddr_length;
1285 dev_ctrl_db[device].fld_info.soc_sram_base = ll_info.soc_sram_base;
1286 dev_ctrl_db[device].fld_info.soc_ddr_base = ll_info.soc_ddr_base;
1287 dev_ctrl_db[device].fld_info.soc_regs_base = ll_info.soc_regs_base;
1288
1289 BCM_LOG(INFO, dev_ctrl_db[device].log_id,
1290 "FLD_INFO: ddr_length=0x%x sram_base=%p soc_ddr_base=%p soc_regs_base=%p\n",
1291 dev_ctrl_db[device].fld_info.soc_ddr_length,
1292 (void *)dev_ctrl_db[device].fld_info.soc_sram_base,
1293 (void *)dev_ctrl_db[device].fld_info.soc_ddr_base,
1294 (void *)dev_ctrl_db[device].fld_info.soc_regs_base);
1295
1296 rc = bcm_fld_register(device, &dev_ctrl_db[device].fld_info);
1297 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_fld_register\n");
1298
1299 return BCM_ERR_OK;
1300}
1301
1302static bcmos_errno dev_ctrl_handle_file(bcmolt_devid device, bcmolt_device_image_type image_type)
1303{
1304 int32_t read_len;
1305 BCM_FLD_HOST_DEBUG_VALUES host_debug_value;
1306 bcmos_errno rc;
1307 uint32_t offset_r = 0, offset_w = 0;
1308 volatile unsigned long write_complete[2];
1309 const char *image_name;
1310
1311 BUG_ON((image_type != BCMOLT_DEVICE_IMAGE_TYPE_BOOTLOADER) && (image_type != BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION));
1312
1313 image_name = image_type == BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION ? "application" : "boot loader";
1314
1315 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Loading %s\n", image_name);
1316
1317 host_debug_value = image_type == BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION ? BCM_FLD_HOST_WRITE_DDR : BCM_FLD_HOST_WRITE_SRAM;
1318 rc = bcm_fld_set_host_debug_status(device, host_debug_value);
1319 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_fld_set_host_debug_status\n");
1320
1321 /* If this is the application image, skip the envelope (jump to the data itself). */
1322 if (image_type == BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION)
1323 {
1324 bcmolt_firmware_envelope envelope;
1325
1326 read_len = dev_ctrl_params.image_read_cb(device, image_type, offset_r, (uint8_t *)&envelope, sizeof(envelope));
1327 if (read_len < sizeof(envelope))
1328 {
1329 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "image_read_cb returned error %s (%d)\n", bcmos_strerror(rc), rc);
1330 return rc;
1331 }
1332 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Upload firmware version=%u.%u.%u.%u\n",
1333 envelope.revision.release_major_id, envelope.revision.release_minor_id, envelope.revision.release_revision_id, envelope.revision.model_id);
1334 offset_r += read_len;
1335 }
1336
1337 do
1338 {
1339 read_len = dev_ctrl_params.image_read_cb(device, image_type, offset_r, image_buf[device], IMAGE_BUF_SIZE);
1340 if (read_len < 0)
1341 {
1342 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "image_read_cb returned error %s (%d)\n", bcmos_strerror(rc), rc);
1343 return rc;
1344 }
1345
1346 if (!read_len)
1347 break;
1348
1349 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Writing %s (%d)\n", image_name, read_len);
1350 rc = bcm_fld_write(device, (char *)image_buf[device], read_len, offset_w, image_type);
1351 if (rc != BCM_ERR_OK)
1352 {
1353 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "bcm_fld_write returned error %s (%d)\n", bcmos_strerror(rc), rc);
1354 return rc;
1355 }
1356
1357 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Reading %s for checking (%d)\n", image_name, read_len);
1358 rc = bcm_fld_read(device, (char *)rd_image_buf[device], (uint32_t *)&read_len, offset_w, image_type);
1359 if (rc != BCM_ERR_OK)
1360 {
1361 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "bcm_fld_read returned error %s (%d)\n", bcmos_strerror(rc), rc);
1362 return rc;
1363 }
1364
1365 offset_r += read_len;
1366 offset_w += read_len;
1367
1368 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Comparing %s (%d)/(%u)\n", image_name, read_len, offset_w);
1369 if (memcmp(rd_image_buf[device], image_buf[device], read_len))
1370 {
1371 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Error during image uploading %x\n", offset_w);
1372 return BCM_ERR_INTERNAL;
1373 }
1374 } while (read_len);
1375
1376 if (!offset_w)
1377 {
1378 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "%s image file empty or corrupted!!!\n", image_name);
1379 return BCM_ERR_INTERNAL;
1380 }
1381
1382 if (image_type == BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION)
1383 {
1384 read_len = sizeof(unsigned long);
1385 /* first read word from star of the image */
1386 bcm_fld_read(device, (char *)(long)&write_complete[0], (uint32_t *)&read_len, 0, image_type);
1387 /* sync before read tail of image */
1388 bcmos_barrier();
1389 /* read from tail of the image */
1390 bcm_fld_read(
1391 device,
1392 (char *)(long)&write_complete[1],
1393 (uint32_t *)&read_len,
1394 offset_w - sizeof(unsigned long),
1395 image_type);
1396 /* now we can be sure that full image in the embedded memory */
1397 }
1398
1399 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Transferred %u bytes\n", offset_w);
1400
1401 return BCM_ERR_OK;
1402}
1403
1404static bcmos_errno dev_ctrl_handle_application_image(bcmolt_devid device)
1405{
1406 bcmolt_device_cfg_data *dev_params = &dev_ctrl_db[device].device_params;
1407 bcmos_errno rc = BCM_ERR_OK;
1408
1409 rc = dev_ctrl_handle_file(device, BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION);
1410 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "dev_ctrl_handle_file()\n");
1411 rc = bcm_fld_host_finish_write_ddr(device, 0);
1412 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_fld_host_finish_write_ddr()\n");
1413 rc = bcmtrmux_connect(device, dev_params->debug.host_dma_tx_queue_size, dev_params->debug.host_dma_rx_queue_size);
1414 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcmtrmux_connect()\n");
1415 /* We want that in case ONLY the host is reset, Maple enters standalone mode - this means we need to turn off "hot reset" on the PCIe channel. */
1416 rc = bcm_ll_pcie_host_reset_enable(device,BCMOS_FALSE);
1417 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_ll_pcie_host_reset_enable()\n");
1418
1419 return rc;
1420}
1421
1422static bcmos_errno dev_ctrl_handle_bootloader_image(bcmolt_devid device, uint32_t test_ddr)
1423{
1424 bcmos_errno rc = BCM_ERR_OK;
1425
1426 rc = dev_ctrl_handle_file(device, BCMOLT_DEVICE_IMAGE_TYPE_BOOTLOADER);
1427 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "dev_ctrl_handle_file()\n");
1428 rc = bcm_fld_start_bootloader(device, test_ddr);
1429 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_fld_start_bootloader()\n");
1430 bcmos_timer_start(
1431 &dev_ctrl_db[device].boot_seq_info.timer.timer,
1432 dev_ctrl_db[device].boot_seq_info.polling_interval);
1433
1434 return rc;
1435}
1436
1437static bcmos_errno dev_ctrl_start_fld(bcmolt_devid device, uint32_t test_ddr)
1438{
1439 bcmos_errno rc = BCM_ERR_OK;
1440
1441 bcm_fld_clear_comm_area(device);
1442
1443 rc = dev_ctrl_handle_bootloader_image(device, test_ddr);
1444 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "dev_ctrl_handle_bootloader_image\n");
1445
1446 return rc;
1447}
1448
1449static bcmos_errno dev_ctrl_get_exception_log_by_cpu(bcmolt_devid device, uint32_t cpuid)
1450{
1451 char *exception_buf;
1452 int exception_buf_len;
1453 bcmos_errno rc;
1454
1455 exception_buf = bcmos_alloc(BCM_FLD_CPU_POSTMORTEM_BUF_SIZE);
1456 rc = bcm_fld_copy_exception_log(device, cpuid, exception_buf, &exception_buf_len);
1457 if (rc)
1458 {
1459 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "bcm_fld_copy_exception_log failed, rc=%u (%s)\n", rc, bcmos_strerror(rc));
1460 goto exit;
1461 }
1462 bcm_fld_clear_exception_state(device, cpuid);
1463
1464 dev_ctrl_send_ind_exception_log(device, cpuid, exception_buf);
1465 rc = BCM_ERR_OK;
1466
1467exit:
1468 bcmos_free(exception_buf);
1469 return rc;
1470}
1471
1472/** Dump exception log if there is one, return BCM_ERR_NOENT if not. */
1473static bcmos_errno dev_ctrl_get_exception_log_if_present(bcmolt_devid dev_id)
1474{
1475 bcmos_errno rc;
1476 uint32_t state0, state1;
1477
1478 /* Dump exception log, if any.
1479 * This should be done prior to writing bootloader, as it will overwrite the same place in SRAM. */
1480 rc = bcm_fld_get_exception_state(dev_id, &state0, &state1);
1481 BCM_DEV_CTRL_RETURN_ON_ERROR(dev_id, rc, "bcm_fld_get_exception_state\n");
1482 if (state0)
1483 dev_ctrl_get_exception_log_by_cpu(dev_id, 0);
1484 if (state1)
1485 dev_ctrl_get_exception_log_by_cpu(dev_id, 1);
1486 if (!state0 && !state1)
1487 return BCM_ERR_NOENT;
1488
1489 return BCM_ERR_OK;
1490}
1491
1492/** Dump exception log if there is one, print a message and return BCM_ERR_OK if not. */
1493static bcmos_errno dev_ctrl_get_exception_log(bcmolt_devid dev_id)
1494{
1495 bcmos_errno rc = dev_ctrl_get_exception_log_if_present(dev_id);
1496 if (rc == BCM_ERR_NOENT)
1497 {
1498 BCM_LOG(DEBUG, dev_ctrl_db[dev_id].log_id, "Exception log for device %d is empty\n", dev_id);
1499 rc = BCM_ERR_OK;
1500 }
1501 return rc;
1502}
1503
1504static void dev_ctrl_sw_error_table_dump(bcmolt_devid dev_id)
1505{
1506 bcmos_errno err = dev_ctrl_get_sw_error_table(dev_id);
1507 uint8_t i;
1508
1509 if (BCM_ERR_OK != err)
1510 {
1511 BCM_LOG(INFO, dev_ctrl_db[dev_id].log_id, "Failed to retrieve Embedded Software Error(s): %d\n", err);
1512 }
1513 else
1514 {
1515 BCM_LOG(INFO, dev_ctrl_db[dev_id].log_id, "Found %u Embedded Software Error(s):\n", dev_ctrl_db[dev_id].sw_error_count);
1516 for (i = 0; i < dev_ctrl_db[dev_id].sw_error_count; i++)
1517 {
1518 BCM_LOG(INFO, dev_ctrl_db[dev_id].log_id,
1519 "\t[%s] %s:%u inst:%u count:%u first:%llu last:%llu\n",
1520 dev_ctrl_db[dev_id].sw_errors[i].task_name,
1521 dev_ctrl_db[dev_id].sw_errors[i].filename,
1522 dev_ctrl_db[dev_id].sw_errors[i].line_number,
1523 dev_ctrl_db[dev_id].sw_errors[i].instance,
1524 dev_ctrl_db[dev_id].sw_errors[i].error_counter,
1525 (unsigned long long)dev_ctrl_db[dev_id].sw_errors[i].first_error_time_us,
1526 (unsigned long long)dev_ctrl_db[dev_id].sw_errors[i].last_error_time_us);
1527 }
1528 }
1529}
1530#endif
1531
1532static bcmolt_host_connection_fail_reason dev_ctrl_connect_from_reset(bcmolt_devid device, uint32_t test_ddr)
1533{
1534#ifndef IN_BAND
1535 bcmos_errno rc;
1536
1537 rc = dev_ctrl_params.device_on_cb(device);
1538 BCMOS_TRACE_CHECK_RETURN(
1539 rc != BCM_ERR_OK,
1540 BCMOLT_HOST_CONNECTION_FAIL_REASON_USER_CALLBACK_ERROR,
1541 "device_on_cb\n");
1542
1543 rc = dev_ctrl_params.pcie_channel_prepare_cb(device);
1544 BCMOS_TRACE_CHECK_RETURN(
1545 rc != BCM_ERR_OK,
1546 BCMOLT_HOST_CONNECTION_FAIL_REASON_USER_CALLBACK_ERROR,
1547 "pcie_channel_prepare_cb\n");
1548
1549
1550 rc = dev_ctrl_register_fld(device);
1551 BCMOS_TRACE_CHECK_RETURN(
1552 rc != BCM_ERR_OK,
1553 BCMOLT_HOST_CONNECTION_FAIL_REASON_INTERNAL_ERROR,
1554 "dev_ctrl_register_fld\n");
1555
1556 dev_ctrl_get_exception_log(device);
1557 dev_ctrl_sw_error_table_dump(device);
1558
1559#ifndef SIMULATION_BUILD
1560 bcm_fld_set_host_event(device, dev_ctrl_db[device].trx_disable_mask);
1561#endif
1562 rc = dev_ctrl_start_fld(device, test_ddr);
1563 BCMOS_TRACE_CHECK_RETURN(
1564 rc != BCM_ERR_OK,
1565 BCMOLT_HOST_CONNECTION_FAIL_REASON_INTERNAL_ERROR,
1566 "dev_ctrl_start_fld\n");
1567#endif
1568 return BCMOLT_HOST_CONNECTION_FAIL_REASON_NONE;
1569}
1570
1571static bcmolt_host_connection_fail_reason dev_ctrl_connect_to_standalone(bcmolt_devid device)
1572{
1573 bcmos_errno rc;
1574
1575 /* if Maple runs in standalone mode, and host did reset, we need to register maple to fld and and
1576 reconnect the transport layer - no need to rescan, it was done automatically by host when
1577 ll_pcie registered maple
1578 re-scan without passing thru remove and maple off, lets maple out of reset, remapped, but stucked
1579 not, really, working in standaloane mode
1580 */
1581
1582 /* The chip is running and the PCIe channel hardware is initialized, we can now safely:
1583 * - Register with the FLD driver.
1584 * - Restart the PCIe connection process. As part of this process, the host will set the 'host queues valid' flag.
1585 * If the device is running and sees this flag is set, it will start the reconnection process as well, in sync
1586 * with the host. If the device fails to connect, it means that the device is unresponsive, so the best we can do
1587 * is reset the device and reprogram it from scratch. */
1588#ifndef IN_BAND
1589 rc = dev_ctrl_register_fld(device);
1590 BCMOS_TRACE_CHECK_RETURN(
1591 rc != BCM_ERR_OK,
1592 BCMOLT_HOST_CONNECTION_FAIL_REASON_INTERNAL_ERROR,
1593 "dev_ctrl_register_fld\n");
1594
1595 dev_ctrl_get_exception_log(device);
1596
1597#ifndef SIMULATION_BUILD
1598 bcm_fld_set_host_event(device, dev_ctrl_db[device].trx_disable_mask);
1599#endif
1600#endif
1601
1602 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Requesting re-connect to running device...\n");
1603#ifndef IN_BAND
1604 rc = bcmtrmux_connect(
1605 device,
1606 dev_ctrl_db[device].device_params.debug.host_dma_tx_queue_size,
1607 dev_ctrl_db[device].device_params.debug.host_dma_rx_queue_size);
1608#else
1609 /*Need to pass in IP Address and UDP port when running in linux user space*/
1610 rc = bcmtrmux_connect(device,
1611 dev_ctrl_db[device].device_params.device_ip_address,
1612 dev_ctrl_db[device].device_params.device_udp_port);
1613
1614#endif
1615
1616 if (rc == BCM_ERR_OK)
1617 {
1618 dev_ctrl_db[device].connection_info.state = DEV_CTRL_CONNECTING_STATE_STANDALONE;
1619 return BCMOLT_HOST_CONNECTION_FAIL_REASON_NONE;
1620 }
1621 else
1622 {
1623 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Connection failed - running device didn't respond to connection request\n");
1624 return BCMOLT_HOST_CONNECTION_FAIL_REASON_RECONNECT_TIMEOUT;
1625 }
1626}
1627
1628static void dev_ctrl_disconnect(bcmolt_devid device)
1629{
1630 bcmos_errno rc;
1631
1632 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_DISCONNECTED;
1633#ifdef ENABLE_LOG
1634 dev_ctrl_db[device].sram_log_offset = 0;
1635 dev_ctrl_db[device].msgs_read = 0;
1636#endif
1637 stop_keep_alive_process(&dev_ctrl_db[device].ka_info);
1638 bcmos_timer_stop(&dev_ctrl_db[device].exception_monitor_timer.timer);
1639 dev_ctrl_init_connection_state(device);
1640 rc = bcmtrmux_disconnect(device);
1641 if (rc != BCM_ERR_OK && rc != BCM_ERR_ALREADY)
1642 {
1643 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "bcmtrmux_disconnect returned error: %s (%d)\n", bcmos_strerror(rc), rc);
1644 }
1645}
1646
1647static bcmos_errno dev_ctrl_perform_reset_device(bcmolt_devid device)
1648{
1649 bcmos_errno rc = BCM_ERR_OK;
1650
1651 dev_ctrl_disconnect(device);
1652
1653#ifndef IN_BAND
1654 rc = dev_ctrl_params.pcie_channel_remove_cb(device);
1655 if (rc != BCM_ERR_OK)
1656 {
1657 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Device remove callback failed: %s (%d)\n", bcmos_strerror(rc), rc);
1658 }
1659 rc = dev_ctrl_params.device_off_cb(device);
1660 if (rc != BCM_ERR_OK)
1661 {
1662 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Device off callback failed: %s (%d)\n", bcmos_strerror(rc), rc);
1663 }
1664
1665 /* the device has been reset so our FLD info is now invalid */
1666 dev_ctrl_db[device].fld_info.soc_sram_base = 0;
1667 bcm_fld_unregister(device);
1668#endif
1669 return rc;
1670}
1671static bcmos_errno dev_ctrl_perform_reset(bcmolt_devid device, const bcmolt_msg *msg)
1672{
1673 bcmos_errno rc = BCM_ERR_OK;
1674 bcmolt_device_reset_mode mode = ((const bcmolt_device_reset *)msg)->data.mode;
1675 bcmolt_devid i;
1676
1677 switch (mode)
1678 {
1679 case BCMOLT_DEVICE_RESET_MODE_DEVICE:
1680 return dev_ctrl_perform_reset_device(device);
1681
1682 case BCMOLT_DEVICE_RESET_MODE_HOST:
1683 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_DISCONNECTED;
1684 dev_ctrl_db[device].is_host_reset_pending = BCMOS_TRUE;
1685 dev_ctrl_send_device_disconnect_msg(device, 0);
1686 /* instead of resetting the host right away, wait a few ms so the host can receive the ack / indication */
1687 bcmos_timer_start(&dev_ctrl_db[device].reset_delay_timer.timer, HOST_RESET_DELAY_US);
1688 break;
1689
1690 case BCMOLT_DEVICE_RESET_MODE_ALL:
1691 for (i = 0; i < BCMTR_MAX_OLTS; i++)
1692 {
1693 dev_ctrl_db[i].device_params.state = BCMOLT_DEVICE_STATE_DISCONNECTED;
1694 dev_ctrl_db[i].is_host_reset_pending = BCMOS_TRUE;
1695 rc = dev_ctrl_params.device_off_cb(i);
1696 if (rc != BCM_ERR_OK)
1697 {
1698 BCM_LOG(ERROR, dev_ctrl_db[i].log_id, "Device off callback failed: %s (%d)\n", bcmos_strerror(rc), rc);
1699 }
1700 }
1701 /* instead of resetting the host right away, wait a few ms so the host can receive the ack / indication */
1702 bcmos_timer_start(&dev_ctrl_db[device].reset_delay_timer.timer, HOST_RESET_DELAY_US);
1703 break;
1704
1705 default:
1706 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Unrecognized reset mode: %d\n", mode);
1707 break;
1708 }
1709
1710 return rc;
1711}
1712
1713static void dev_ctrl_disconnected_state_device_clear_event(bcmolt_devid device, const bcmolt_msg *msg)
1714{
1715 dev_ctrl_clear_device_cfg(device);
1716}
1717
1718static void dev_ctrl_disconnected_state_device_config_set_event(bcmolt_devid device, const bcmolt_msg *msg)
1719{
1720 if (dev_ctrl_db[device].last_message == NULL)
1721 {
1722 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Our saved message was invalid\n");
1723 return;
1724 }
1725
1726 dev_ctrl_update_local_configuration(device, msg);
1727 dev_ctrl_db[device].last_message->dir = BCMOLT_MSG_DIR_RESPONSE;
1728 bcmtrmux_control_to_host(device, dev_ctrl_db[device].last_message);
1729 bcmolt_msg_free(dev_ctrl_db[device].last_message);
1730 dev_ctrl_db[device].last_message = NULL;
1731}
1732
1733static void dev_ctrl_disconnected_state_device_config_get_event(bcmolt_devid device, const bcmolt_msg *msg)
1734{
1735 bcmolt_presence_mask mask;
1736 bcmolt_device_cfg *cfg;
1737
1738 if (dev_ctrl_db[device].last_message == NULL)
1739 {
1740 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Our saved message was invalid --- aborting\n");
1741 return;
1742 }
1743
1744 cfg = (bcmolt_device_cfg *)dev_ctrl_db[device].last_message;
1745 cfg->data = dev_ctrl_db[device].device_params;
1746 mask = dev_ctrl_fill_from_local(device);
1747
1748 if ((mask & ~dev_ctrl_db[device].device_params_present) != 0)
1749 {
1750 bcmolt_msg_err(
1751 dev_ctrl_db[device].last_message,
1752 DEV_LOG_INVALID_ID,
1753 BCM_ERR_INVALID_OP,
1754 BCMOLT_ERR_FIELD_NONE,
1755 "Unable to get parameters that have never been set");
1756 }
1757
1758 dev_ctrl_db[device].last_message->dir = BCMOLT_MSG_DIR_RESPONSE;
1759 bcmtrmux_control_to_host(device, dev_ctrl_db[device].last_message);
1760 bcmolt_msg_free(dev_ctrl_db[device].last_message);
1761 dev_ctrl_db[device].last_message = NULL;
1762}
1763
1764static void dev_ctrl_disconnected_state_device_connect_event(bcmolt_devid device, const bcmolt_msg *msg)
1765{
1766#ifdef IN_BAND
1767 bcmolt_device_connect oper;
1768 bcmolt_device_key key = {};
1769#else
1770 bcmos_errno rc;
1771#endif
1772 bcmolt_host_connection_fail_reason fail_reason;
1773 bcmos_bool is_standalone;
1774
1775 if (dev_ctrl_db[device].is_host_reset_pending)
1776 {
1777 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Cannot connect while host reset is pending\n");
1778 return;
1779 }
1780
1781#ifndef IN_BAND
1782 /* Check if the chip is running in standalone mode */
1783
1784 rc = dev_ctrl_params.device_is_running_cb(device, &is_standalone);
1785
1786 if (rc != BCM_ERR_OK)
1787 {
1788 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "device_status_get_cb returned error: %s (%d)\n", bcmos_strerror(rc), rc);
1789 return;
1790 }
1791 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "device_status_get_cb returned success: is_standalone=%s\n", is_standalone ? "yes" : "no");
1792
1793 /* If the chip is running in standalone mode, connect to it:
1794 * - Check the status of the PCIe channel and prepare it if necessary, using host callbacks
1795 * - Register the device in the FLD driver
1796 * - Use FLD to ask the device to re-initialize its PCIe transport layer
1797 * - Initialize the host PCIe transport layer
1798 * Otherwise, we must start the boot sequence:
1799 * - Power on the device
1800 * - Prepare the PCIe channel via host callback
1801 * - Register the device in the FLD driver
1802 * - Check if there is an exception log from the last time the application was run (and print it if so)
1803 * - Start the FLD timer to load the bootcode
1804 * In either case, the resulting state is 'connecting'.
1805 */
1806 dev_ctrl_db[device].boot_seq_info.polling_counter = BOOT_SEQ_POLLING_MAX_NUMBER;
1807 bcmos_timer_handler_set(&dev_ctrl_db[device].boot_seq_info.timer.timer, dev_ctrl_boot_seq_timer_handler, device);
1808#else
1809 is_standalone= BCMOS_TRUE;
1810#endif
1811 if (is_standalone)
1812 {
1813 fail_reason = dev_ctrl_connect_to_standalone(device);
1814 }
1815 else
1816 {
1817 fail_reason = dev_ctrl_connect_from_reset(device, 0);
1818 dev_ctrl_db[device].connection_info.state = DEV_CTRL_CONNECTING_STATE_ESTABLISHING;
1819 }
1820
1821 if (fail_reason == BCMOLT_HOST_CONNECTION_FAIL_REASON_NONE)
1822 {
1823 bcmos_timer_start(&dev_ctrl_db[device].connection_info.timer.timer, DEVICE_CONTROL_CONNECT_TIME_US);
1824 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_CONNECTING;
1825 BCM_LOG(DEBUG, dev_ctrl_db[device].log_id, "began connecting to %s\n", is_standalone ? "standby device" : "device from reset");
1826
1827#ifndef IN_BAND
1828 /*Do nothing*/
1829#else
1830 BCMOLT_OPER_INIT(&oper, device, connect, key);
1831 oper.hdr.hdr.type = BCMOLT_MSG_TYPE_SET;
1832 (void)bcmtrmux_control_to_line(device, &oper.hdr.hdr);
1833 bcmos_printf("Sent connect to embedded...\n");
1834#endif
1835
1836 }
1837 else
1838 {
1839 BCM_LOG(ERROR, dev_ctrl_db[device].log_id,
1840 "failed to begin connection process: %s (%d)\n",
1841 bcm_str_host_connection_fail_reason(fail_reason),
1842 fail_reason);
1843 dev_ctrl_send_ind_connection_failure(device, fail_reason);
1844 }
1845}
1846
1847static void dev_ctrl_disconnected_state_device_reset_event(bcmolt_devid device, const bcmolt_msg *msg)
1848{
1849 dev_ctrl_perform_reset(device, msg);
1850}
1851
1852#ifndef IN_BAND
1853static void dev_ctrl_disconnected_state_device_run_ddr_test_event(bcmolt_devid device, const bcmolt_msg *msg)
1854{
1855 bcmolt_host_connection_fail_reason fail_reason;
1856 uint32_t test_ddr = 0;
1857
1858 const bcmolt_device_run_ddr_test_data *params = &((const bcmolt_device_run_ddr_test *)msg)->data;
1859 if (params->cpu)
1860 {
1861 test_ddr |= BCM_FLD_HOST_RUN_CPU_DDR_TEST_MASK;
1862 }
1863 if (params->ras_0)
1864 {
1865 test_ddr |= BCM_FLD_HOST_RUN_RAS_0_TEST_MASK;
1866 }
1867 if (params->ras_1)
1868 {
1869 test_ddr |= BCM_FLD_HOST_RUN_RAS_1_TEST_MASK;
1870 }
1871
1872 dev_ctrl_db[device].boot_seq_info.polling_counter = DDR_TEST_POLLING_MAX_NUMBER;
1873 bcmos_timer_handler_set(&dev_ctrl_db[device].boot_seq_info.timer.timer, dev_ctrl_ddr_test_timer_handler, device);
1874 fail_reason = dev_ctrl_connect_from_reset(device, test_ddr);
1875 if (fail_reason == BCMOLT_HOST_CONNECTION_FAIL_REASON_NONE)
1876 {
1877 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_TESTING_DDR;
1878 }
1879 else
1880 {
1881 bcmolt_device_ddr_test_complete ind = {};
1882 BCMOLT_AUTO_INIT(&ind, device, ddr_test_complete);
1883 ind.data.ddr_test.status = BCMOLT_DDR_TEST_STATUS_CONNECTION_FAILED;
1884 ind.data.ddr_test.u.connection_failed.reason = fail_reason;
1885 dev_ctrl_send_indication(device, &ind.hdr.hdr);
1886 }
1887
1888}
1889
1890static void dev_ctrl_testing_ddr_state_ddr_test_completed_event(bcmolt_devid device, const bcmolt_msg *msg)
1891{
1892 bcmolt_device_ddr_test_complete ind = {};
1893
1894 BCMOLT_AUTO_INIT(&ind, device, ddr_test_complete);
1895
1896 ind.data.ddr_test.status = BCMOLT_DDR_TEST_STATUS_COMPLETED;
1897 ind.data.ddr_test.u.completed.cpu_result = bcm_fld_ddr_test_result_get(device, 0);
1898 ind.data.ddr_test.u.completed.ras_0_result = bcm_fld_ddr_test_result_get(device, 1);
1899 ind.data.ddr_test.u.completed.ras_1_result = bcm_fld_ddr_test_result_get(device, 2);
1900
1901 dev_ctrl_perform_reset_device(device);
1902 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_DISCONNECTED;
1903
1904 dev_ctrl_send_indication(device, &ind.hdr.hdr);
1905}
1906
1907static void dev_ctrl_testing_ddr_state_ddr_test_timeout_event(bcmolt_devid device, const bcmolt_msg *msg)
1908{
1909 bcmolt_device_ddr_test_complete ind = {};
1910
1911 dev_ctrl_perform_reset_device(device);
1912 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_DISCONNECTED;
1913
1914 BCMOLT_AUTO_INIT(&ind, device, ddr_test_complete);
1915 ind.data.ddr_test.status = BCMOLT_DDR_TEST_STATUS_TIMEOUT;
1916 dev_ctrl_send_indication(device, &ind.hdr.hdr);
1917}
1918#endif
1919
1920static void dev_ctrl_connecting_state_connection_failure_event(bcmolt_devid device, const bcmolt_msg *msg)
1921{
1922 dev_ctrl_disconnect(device);
1923 dev_ctrl_send_ind_connection_failure_from_msg(device, msg);
1924}
1925
1926static void dev_ctrl_connecting_state_connection_established_event(bcmolt_devid device, const bcmolt_msg *msg)
1927{
1928 if (dev_ctrl_db[device].connection_info.state == DEV_CTRL_CONNECTING_STATE_ESTABLISHING)
1929 {
1930 /* Initial connection is complete, now wait for the firmware to be initialized. */
1931 dev_ctrl_db[device].connection_info.state = DEV_CTRL_CONNECTING_STATE_CONFIGURING;
1932 dev_ctrl_send_config_set_msg(
1933 device,
1934 dev_ctrl_db[device].device_params_present,
1935 0,
1936 &dev_ctrl_db[device].device_params);
1937 if (dev_ctrl_db[device].connection_info.config_send_counter > 0)
1938 {
1939 dev_ctrl_db[device].connection_info.config_send_counter--;
1940 }
1941 bcmos_timer_start(
1942 &dev_ctrl_db[device].connection_info.timer.timer,
1943 dev_ctrl_db[device].connection_info.config_interval);
1944 }
1945 else
1946 {
1947 /* Initial connection was already done - something must have gone wrong. Try again. */
1948 if (dev_ctrl_db[device].connection_info.config_send_counter > 0)
1949 {
1950 dev_ctrl_send_config_set_msg(
1951 device,
1952 dev_ctrl_db[device].device_params_present,
1953 0,
1954 &dev_ctrl_db[device].device_params);
1955 bcmos_timer_start(
1956 &dev_ctrl_db[device].connection_info.timer.timer,
1957 dev_ctrl_db[device].connection_info.config_interval);
1958 dev_ctrl_db[device].connection_info.config_send_counter--;
1959 }
1960 else
1961 {
1962 dev_ctrl_disconnect(device);
1963 dev_ctrl_send_ind_connection_failure(device, BCMOLT_HOST_CONNECTION_FAIL_REASON_TIMEOUT);
1964 }
1965 }
1966}
1967
1968static inline bcmos_bool dev_ctrl_nni_speed_equal(const bcmolt_device_nni_speed *a, const bcmolt_device_nni_speed *b)
1969{
1970 return (a->first_half == b->first_half && a->second_half == b->second_half);
1971}
1972
1973static void dev_ctrl_connecting_state_device_ready_event(bcmolt_devid device, const bcmolt_msg *msg)
1974{
1975 bcmos_errno rc;
1976 const bcmolt_device_device_ready *ready_msg = (const bcmolt_device_device_ready *)msg;
1977 bcmolt_host_connection_fail_reason fail_reason = BCMOLT_HOST_CONNECTION_FAIL_REASON__NUM_OF;
1978
1979 if (dev_ctrl_db[device].connection_info.state == DEV_CTRL_CONNECTING_STATE_ESTABLISHING)
1980 {
1981 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Unexpected 'device ready' indication before connection is established\n");
1982 return;
1983 }
1984
1985 if (ready_msg->data.system_mode != dev_ctrl_db[device].device_params.system_mode)
1986 {
1987 fail_reason = BCMOLT_HOST_CONNECTION_FAIL_REASON_SYSTEM_MODE_MISMATCH;
1988 }
1989 else if ((dev_ctrl_db[device].device_params_present & BCMOLT_PROP_MASK_GET(device, _cfg, nni_speed)) != 0 &&
1990 !dev_ctrl_nni_speed_equal(&ready_msg->data.nni_speed, &dev_ctrl_db[device].device_params.nni_speed))
1991 {
1992 fail_reason = BCMOLT_HOST_CONNECTION_FAIL_REASON_NNI_SPEED_MISMATCH;
1993 }
1994 else
1995 {
1996 rc = dev_ctrl_validate_fw_version(device, &ready_msg->data.firmware_sw_version);
1997 if (rc != BCM_ERR_OK)
1998 {
1999 fail_reason = BCMOLT_HOST_CONNECTION_FAIL_REASON_SOFTWARE_VERSION_MISMATCH;
2000 }
2001 }
2002
2003 if (fail_reason == BCMOLT_HOST_CONNECTION_FAIL_REASON__NUM_OF)
2004 {
2005 dev_ctrl_db[device].device_params.firmware_sw_version = ready_msg->data.firmware_sw_version;
2006 dev_ctrl_db[device].device_params.chip_revision = ready_msg->data.chip_revision;
2007 if ((dev_ctrl_db[device].device_params_present & BCMOLT_PROP_MASK_GET(device, _cfg, nni_speed)) == 0)
2008 {
2009 dev_ctrl_db[device].device_params.nni_speed = ready_msg->data.nni_speed;
2010 dev_ctrl_db[device].device_params_present |= BCMOLT_PROP_MASK_GET(device, _cfg, nni_speed);
2011 }
2012
2013 if (dev_ctrl_db[device].ka_info.ka_interval > 0)
2014 {
2015 start_keep_alive_process(&dev_ctrl_db[device].ka_info);
2016 }
2017
2018#ifndef IN_BAND
2019 bcmos_timer_start(&dev_ctrl_db[device].exception_monitor_timer.timer, EXCEPTION_LOG_MONITOR_INTERVAL);
2020#endif
2021 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_READY;
2022 dev_ctrl_send_ind_connection_complete(
2023 device,
2024 dev_ctrl_db[device].connection_info.state == DEV_CTRL_CONNECTING_STATE_STANDALONE);
2025 }
2026 else
2027 {
2028 dev_ctrl_send_device_disconnect_msg(device, 0);
2029 dev_ctrl_disconnect(device);
2030 dev_ctrl_send_ind_connection_failure(device, fail_reason);
2031 }
2032}
2033
2034static void dev_ctrl_connecting_state_received_ack(bcmolt_devid device, const bcmolt_msg *msg)
2035{
2036 /* This is called when we receive the ACK response against the configuraiton set message which was sent while the
2037 * state-machine as part of the initial connection process. If the result is OK, we should just move on and keep
2038 * waiting for the "ready" indication. If the result is not OK, the device rejected the configuration so we
2039 * should disconnect the device and send a failure indication. */
2040 if (msg->err != BCM_ERR_OK)
2041 {
2042 bcmolt_host_connection_fail_reason fail_reason;
2043
2044 dev_ctrl_disconnect(device);
2045
2046 /* Figure out which failure reason based on the message error code. */
2047 switch (msg->err)
2048 {
2049 case BCM_ERR_NOT_SUPPORTED:
2050 fail_reason = BCMOLT_HOST_CONNECTION_FAIL_REASON_SYSTEM_MODE_NOT_SUPPORTED;
2051 break;
2052 case BCM_ERR_PARM:
2053 fail_reason = BCMOLT_HOST_CONNECTION_FAIL_REASON_PARAMETER;
2054 break;
2055 default:
2056 fail_reason = BCMOLT_HOST_CONNECTION_FAIL_REASON_INTERNAL_ERROR;
2057 break;
2058 }
2059
2060 dev_ctrl_send_ind_connection_failure(device, fail_reason);
2061 }
2062}
2063
2064static void dev_ctrl_ready_state_device_config_set_event(bcmolt_devid device, const bcmolt_msg *msg)
2065{
2066 const bcmolt_device_cfg *cfg = (const bcmolt_device_cfg *)msg;
2067
2068 dev_ctrl_send_config_set_msg(device, msg->presence_mask, dev_ctrl_db[device].last_message->corr_tag, &cfg->data);
2069
2070 bcmos_timer_start(&dev_ctrl_db[device].device_response_timer.timer, DEVICE_RESPONSE_TIMEOUT_LENGTH);
2071 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_WAITING_FOR_DEVICE;
2072}
2073
2074static void dev_ctrl_ready_state_device_config_get_event(bcmolt_devid device, const bcmolt_msg *msg)
2075{
2076 bcmolt_presence_mask mask;
2077
2078 if (dev_ctrl_db[device].last_message == NULL)
2079 {
2080 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Our saved message was invalid --- aborting\n");
2081 return;
2082 }
2083
2084 mask = dev_ctrl_fill_from_local(device);
2085 if (mask == 0)
2086 {
2087 dev_ctrl_db[device].last_message->dir = BCMOLT_MSG_DIR_RESPONSE;
2088 bcmtrmux_control_to_host(device, dev_ctrl_db[device].last_message);
2089 bcmolt_msg_free(dev_ctrl_db[device].last_message);
2090 dev_ctrl_db[device].last_message = NULL;
2091 }
2092 else
2093 {
2094 bcmos_timer_start(&dev_ctrl_db[device].device_response_timer.timer, DEVICE_RESPONSE_TIMEOUT_LENGTH);
2095 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_WAITING_FOR_DEVICE;
2096 dev_ctrl_send_config_get_msg(device, mask, dev_ctrl_db[device].last_message->corr_tag);
2097 }
2098}
2099
2100static void dev_ctrl_ready_state_device_disconnect_event(bcmolt_devid device, const bcmolt_msg *msg)
2101{
2102 dev_ctrl_send_device_disconnect_msg(device, 0);
2103 dev_ctrl_disconnect(device);
2104 dev_ctrl_send_ind_disconnection_complete(device);
2105}
2106
2107static void dev_ctrl_ready_state_device_reset_event(bcmolt_devid device, const bcmolt_msg *msg)
2108{
2109 dev_ctrl_perform_reset(device, msg);
2110 dev_ctrl_send_ind_disconnection_complete(device);
2111}
2112
2113static void dev_ctrl_ready_state_connection_failure_event(bcmolt_devid device, const bcmolt_msg *msg)
2114{
2115 dev_ctrl_disconnect(device);
2116 dev_ctrl_send_ind_connection_failure_from_msg(device, msg);
2117}
2118
2119static void dev_ctrl_waiting_for_device_state_timer_timeout(bcmolt_devid device, const bcmolt_msg *msg)
2120{
2121 if (dev_ctrl_db[device].last_message == NULL)
2122 {
2123 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Our saved message was invalid --- aborting\n");
2124 return;
2125 }
2126
2127 bcmolt_msg_err(
2128 dev_ctrl_db[device].last_message,
2129 DEV_LOG_INVALID_ID,
2130 BCM_ERR_INTERNAL,
2131 BCMOLT_ERR_FIELD_NONE,
2132 "No response to configuration message from embedded");
2133 dev_ctrl_db[device].last_message->dir = BCMOLT_MSG_DIR_RESPONSE;
2134 bcmtrmux_control_to_host(device, dev_ctrl_db[device].last_message);
2135 bcmolt_msg_free(dev_ctrl_db[device].last_message);
2136 dev_ctrl_db[device].last_message = NULL;
2137 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_READY;
2138}
2139
2140static void dev_ctrl_waiting_for_device_state_received_ack(bcmolt_devid device, const bcmolt_msg *msg)
2141{
2142 bcmos_timer_stop(&dev_ctrl_db[device].device_response_timer.timer);
2143
2144 if (dev_ctrl_db[device].last_message == NULL)
2145 {
2146 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Our saved message was invalid --- aborting\n");
2147 return;
2148 }
2149
2150 if (msg->corr_tag != dev_ctrl_db[device].last_message->corr_tag)
2151 {
2152 /* ignore this response as it was to something other than our request */
2153 return;
2154 }
2155
2156 if (msg->err != BCM_ERR_OK)
2157 {
2158 dev_ctrl_db[device].last_message->err = msg->err;
2159 dev_ctrl_db[device].last_message->err_field_idx = msg->err_field_idx;
2160 memcpy(dev_ctrl_db[device].last_message->err_text, msg->err_text, sizeof(msg->err_text));
2161 dev_ctrl_db[device].last_message->dir = BCMOLT_MSG_DIR_RESPONSE;
2162 bcmtrmux_control_to_host(device, dev_ctrl_db[device].last_message);
2163 bcmolt_msg_free(dev_ctrl_db[device].last_message);
2164 dev_ctrl_db[device].last_message = NULL;
2165 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_READY;
2166 return;
2167 }
2168
2169 if (msg->type == BCMOLT_MSG_TYPE_GET)
2170 {
2171 const bcmolt_device_cfg *source = (const bcmolt_device_cfg *)msg;
2172 bcmolt_device_cfg *dest = (bcmolt_device_cfg *)dev_ctrl_db[device].last_message;
2173 if (BCMOLT_CFG_PROP_IS_SET(source, device, protection_switching_ext_irq))
2174 {
2175 dest->data.protection_switching_ext_irq = source->data.protection_switching_ext_irq;
2176 }
2177 if (BCMOLT_CFG_PROP_IS_SET(source, device, epon_clock_transport_sample_delay))
2178 {
2179 dest->data.epon_clock_transport_sample_delay = source->data.epon_clock_transport_sample_delay;
2180 }
2181 if (BCMOLT_CFG_PROP_IS_SET(source, device, indication_shaping))
2182 {
2183 dest->data.indication_shaping = source->data.indication_shaping;
2184 }
2185 if (BCMOLT_CFG_PROP_IS_SET(source, device, gpon_xgpon_tod_enable))
2186 {
2187 dest->data.gpon_xgpon_tod_enable = source->data.gpon_xgpon_tod_enable;
2188 }
2189 if (BCMOLT_CFG_PROP_IS_SET(source, device, gpon_xgpon_tod_gpio_pin))
2190 {
2191 dest->data.gpon_xgpon_tod_gpio_pin = source->data.gpon_xgpon_tod_gpio_pin;
2192 }
2193 if (BCMOLT_CFG_PROP_IS_SET(source, device, gpon_xgpon_tod_connected_internally))
2194 {
2195 dest->data.gpon_xgpon_tod_connected_internally = source->data.gpon_xgpon_tod_connected_internally;
2196 }
2197 if (BCMOLT_CFG_PROP_IS_SET(source, device, epon_8021_as_tod_format))
2198 {
2199 dest->data.epon_8021_as_tod_format = source->data.epon_8021_as_tod_format;
2200 }
2201 if (BCMOLT_CFG_PROP_IS_SET(source, device, firmware_sw_version))
2202 {
2203 dest->data.firmware_sw_version = source->data.firmware_sw_version;
2204 }
2205 if (BCMOLT_CFG_PROP_IS_SET(source, device, chip_revision))
2206 {
2207 dest->data.chip_revision = source->data.chip_revision;
2208 }
2209 if (BCMOLT_CFG_PROP_IS_SET(source, device, chip_temperature))
2210 {
2211 dest->data.chip_temperature = source->data.chip_temperature;
2212 }
2213 if (BCMOLT_CFG_PROP_IS_SET(source, device, epon_shaper_mode))
2214 {
2215 dest->data.epon_shaper_mode = source->data.epon_shaper_mode;
2216 }
2217 if (BCMOLT_CFG_PROP_IS_SET(source, device, embedded_image_list))
2218 {
2219 dest->data.embedded_image_list = source->data.embedded_image_list;
2220 }
2221 if (BCMOLT_CFG_PROP_IS_SET(source, device, chip_voltage))
2222 {
2223 dest->data.chip_voltage = source->data.chip_voltage;
2224 }
2225 if (BCMOLT_CFG_PROP_IS_SET(source, device, epon_tod_string))
2226 {
2227 dest->data.epon_tod_string = source->data.epon_tod_string;
2228 }
2229 if (BCMOLT_CFG_PROP_IS_SET(source, device, xgpon_num_of_onus))
2230 {
2231 dest->data.xgpon_num_of_onus = source->data.xgpon_num_of_onus;
2232 }
2233 if (BCMOLT_CFG_PROP_IS_SET(source, device, gpon_xgpon_tod_string_length))
2234 {
2235 dest->data.gpon_xgpon_tod_string_length = source->data.gpon_xgpon_tod_string_length;
2236 }
2237 if (BCMOLT_CFG_PROP_IS_SET(source, device, tod_uart_baudrate))
2238 {
2239 dest->data.tod_uart_baudrate = source->data.tod_uart_baudrate;
2240 }
2241 }
2242
2243 if (msg->type == BCMOLT_MSG_TYPE_SET)
2244 {
2245 bcmolt_device_cfg *source = (bcmolt_device_cfg *)dev_ctrl_db[device].last_message;
2246 bcmolt_device_cfg_data *dest = &dev_ctrl_db[device].device_params;
2247 dev_ctrl_db[device].device_params_present |= source->hdr.hdr.presence_mask;
2248 if (BCMOLT_CFG_PROP_IS_SET(source, device, protection_switching_ext_irq))
2249 {
2250 dest->protection_switching_ext_irq = source->data.protection_switching_ext_irq;
2251 }
2252 if (BCMOLT_CFG_PROP_IS_SET(source, device, epon_clock_transport_sample_delay))
2253 {
2254 dest->epon_clock_transport_sample_delay = source->data.epon_clock_transport_sample_delay;
2255 }
2256 if (BCMOLT_CFG_PROP_IS_SET(source, device, indication_shaping))
2257 {
2258 dest->indication_shaping = source->data.indication_shaping;
2259 }
2260 if (BCMOLT_CFG_PROP_IS_SET(source, device, gpon_xgpon_tod_enable))
2261 {
2262 dest->gpon_xgpon_tod_enable = source->data.gpon_xgpon_tod_enable;
2263 }
2264 if (BCMOLT_CFG_PROP_IS_SET(source, device, gpon_xgpon_tod_gpio_pin))
2265 {
2266 dest->gpon_xgpon_tod_gpio_pin = source->data.gpon_xgpon_tod_gpio_pin;
2267 }
2268 if (BCMOLT_CFG_PROP_IS_SET(source, device, gpon_xgpon_tod_connected_internally))
2269 {
2270 dest->gpon_xgpon_tod_connected_internally = source->data.gpon_xgpon_tod_connected_internally;
2271 }
2272 if (BCMOLT_CFG_PROP_IS_SET(source, device, epon_8021_as_tod_format))
2273 {
2274 dest->epon_8021_as_tod_format = source->data.epon_8021_as_tod_format;
2275 }
2276 if (BCMOLT_CFG_PROP_IS_SET(source, device, epon_tod_string))
2277 {
2278 dest->epon_tod_string = source->data.epon_tod_string;
2279 }
2280 if (BCMOLT_CFG_PROP_IS_SET(source, device, epon_shaper_mode))
2281 {
2282 dest->epon_shaper_mode = source->data.epon_shaper_mode;
2283 }
2284 if (BCMOLT_CFG_PROP_IS_SET(source, device, keepalive_tolerance))
2285 {
2286 dev_ctrl_db[device].ka_info.ka_tolerance = source->data.keepalive_tolerance;
2287 }
2288 if (BCMOLT_CFG_PROP_IS_SET(source, device, keepalive_interval))
2289 {
2290 dev_ctrl_db[device].ka_info.ka_interval = source->data.keepalive_interval * BCMOS_MICROSECONDS_IN_SECONDS;
2291 if (dev_ctrl_db[device].ka_info.ka_interval > 0)
2292 {
2293 start_keep_alive_process(&dev_ctrl_db[device].ka_info);
2294 }
2295 else
2296 {
2297 stop_keep_alive_process(&dev_ctrl_db[device].ka_info);
2298 }
2299 }
2300 if (BCMOLT_CFG_PROP_IS_SET(source, device, gpon_xgpon_tod_string_length))
2301 {
2302 dest->gpon_xgpon_tod_string_length = source->data.gpon_xgpon_tod_string_length;
2303 }
2304 if (BCMOLT_CFG_PROP_IS_SET(source, device, tod_uart_baudrate))
2305 {
2306 dest->tod_uart_baudrate = source->data.tod_uart_baudrate;
2307 }
2308 }
2309
2310 dev_ctrl_db[device].last_message->dir = BCMOLT_MSG_DIR_RESPONSE;
2311 bcmtrmux_control_to_host(device, dev_ctrl_db[device].last_message);
2312 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_READY;
2313 bcmolt_msg_free(dev_ctrl_db[device].last_message);
2314 dev_ctrl_db[device].last_message = NULL;
2315}
2316
2317static dev_ctrl_sm_cb dev_ctrl_sm[BCMOLT_DEVICE_STATE__NUM_OF][DEVICE_CONTROL_EVENT__NUM_OF] =
2318{
2319 [BCMOLT_DEVICE_STATE_DISCONNECTED] =
2320 {
2321 [DEVICE_CONTROL_EVENT_DEVICE_CLEAR] = dev_ctrl_disconnected_state_device_clear_event,
2322 [DEVICE_CONTROL_EVENT_DEVICE_CONFIG_SET] = dev_ctrl_disconnected_state_device_config_set_event,
2323 [DEVICE_CONTROL_EVENT_DEVICE_CONFIG_GET] = dev_ctrl_disconnected_state_device_config_get_event,
2324 [DEVICE_CONTROL_EVENT_DEVICE_CONNECT] = dev_ctrl_disconnected_state_device_connect_event,
2325 [DEVICE_CONTROL_EVENT_DEVICE_RESET] = dev_ctrl_disconnected_state_device_reset_event,
2326#ifndef IN_BAND
2327 [DEVICE_CONTROL_EVENT_RUN_DDR_TEST] = dev_ctrl_disconnected_state_device_run_ddr_test_event,
2328#endif
2329 },
2330
2331 [BCMOLT_DEVICE_STATE_CONNECTING] =
2332 {
2333 [DEVICE_CONTROL_EVENT_CONNECTION_FAILURE] = dev_ctrl_connecting_state_connection_failure_event,
2334 [DEVICE_CONTROL_EVENT_CONNECTION_ESTABLISHED] = dev_ctrl_connecting_state_connection_established_event,
2335 [DEVICE_CONTROL_EVENT_DEVICE_READY] = dev_ctrl_connecting_state_device_ready_event,
2336 [DEVICE_CONTROL_EVENT_DEVICE_RECEIVED_ACK] = dev_ctrl_connecting_state_received_ack,
2337 },
2338
2339 [BCMOLT_DEVICE_STATE_READY] =
2340 {
2341 [DEVICE_CONTROL_EVENT_DEVICE_CONFIG_SET] = dev_ctrl_ready_state_device_config_set_event,
2342 [DEVICE_CONTROL_EVENT_DEVICE_CONFIG_GET] = dev_ctrl_ready_state_device_config_get_event,
2343 [DEVICE_CONTROL_EVENT_DEVICE_DISCONNECT] = dev_ctrl_ready_state_device_disconnect_event,
2344 [DEVICE_CONTROL_EVENT_DEVICE_RESET] = dev_ctrl_ready_state_device_reset_event,
2345 [DEVICE_CONTROL_EVENT_CONNECTION_FAILURE] = dev_ctrl_ready_state_connection_failure_event,
2346 },
2347
2348 [BCMOLT_DEVICE_STATE_WAITING_FOR_DEVICE] =
2349 {
2350 [DEVICE_CONTROL_EVENT_DEVICE_TIMER_TIMEOUT] = dev_ctrl_waiting_for_device_state_timer_timeout,
2351 [DEVICE_CONTROL_EVENT_DEVICE_RECEIVED_ACK] = dev_ctrl_waiting_for_device_state_received_ack
2352 },
2353
2354#ifndef IN_BAND
2355 [BCMOLT_DEVICE_STATE_TESTING_DDR] =
2356 {
2357 [DEVICE_CONTROL_EVENT_DDR_TEST_COMPLETED] = dev_ctrl_testing_ddr_state_ddr_test_completed_event,
2358 [DEVICE_CONTROL_EVENT_DDR_TEST_TIMEOUT] = dev_ctrl_testing_ddr_state_ddr_test_timeout_event
2359 }
2360#endif
2361};
2362
2363static void dev_ctrl_sm_err_cb(bcmolt_devid device, dev_ctrl_event event)
2364{
2365 BCM_LOG(ERROR, dev_ctrl_db[device].log_id,
2366 "Unexpected event: device=%d, state=%s, event=%s\n",
2367 device,
2368 bcm_str_device_state(dev_ctrl_db[device].device_params.state),
2369 bcm_str_device_event(event));
2370}
2371
2372static void dev_ctrl_sm_call_state_cb(bcmolt_devid device, dev_ctrl_event event, const bcmolt_msg *msg)
2373{
2374 dev_ctrl_sm_cb cb;
2375 dev_ctrl_db[device].last_event = event;
2376 cb = dev_ctrl_sm[dev_ctrl_db[device].device_params.state][event];
2377 if (cb == NULL)
2378 {
2379 dev_ctrl_sm_err_cb(device, event);
2380 }
2381 else
2382 {
2383 cb(device, msg);
2384 }
2385}
2386
2387static void dev_ctrl_ka_rx_handler(bcmolt_devid device, bcmolt_device_device_keep_alive *msg)
2388{
2389 keep_alive_rx_handler((const bcmos_keep_alive_data_msg *)&msg->data, &dev_ctrl_db[device].ka_info);
2390}
2391
2392static bcmos_errno dev_ctrl_ka_tx_handler(bcmolt_devid device, bcmolt_msg *msg)
2393{
2394 bcmos_errno rc;
2395
2396 if (!dev_ctrl_is_connected(dev_ctrl_db[device].device_params.state))
2397 {
2398 return BCM_ERR_OK; /* in case this happens during a disconnect/reset operation */
2399 }
2400
2401 msg->corr_tag = ++dev_ctrl_db[device].corr_tag;
2402 rc = bcmtrmux_control_to_line(device, msg);
2403 return rc;
2404}
2405
2406static bcmos_errno dev_ctrl_ka_disconnect_handler(bcmolt_devid device)
2407{
2408 dev_ctrl_disconnect(device);
2409 dev_ctrl_send_ind_connection_failure(device, BCMOLT_HOST_CONNECTION_FAIL_REASON_KEEPALIVE);
2410 return BCM_ERR_OK;
2411}
2412
2413static void handle_oper_set_msg(bcmolt_devid device, bcmolt_msg *msg)
2414{
2415 dev_ctrl_event event;
2416
2417 switch (msg->subgroup)
2418 {
2419 case BCMOLT_DEVICE_OPER_ID_RESET:
2420 event = DEVICE_CONTROL_EVENT_DEVICE_RESET;
2421 break;
2422 case BCMOLT_DEVICE_OPER_ID_CONNECT:
2423 event = DEVICE_CONTROL_EVENT_DEVICE_CONNECT;
2424 break;
2425 case BCMOLT_DEVICE_OPER_ID_DISCONNECT:
2426 event = DEVICE_CONTROL_EVENT_DEVICE_DISCONNECT;
2427 break;
2428 case BCMOLT_DEVICE_OPER_ID_RUN_DDR_TEST:
2429 event = DEVICE_CONTROL_EVENT_RUN_DDR_TEST;
2430 break;
2431 default :
2432 event = DEVICE_CONTROL_EVENT_NO_EVENT;
2433 break;
2434 }
2435
2436 /* Send response to the waiting application */
2437 msg->dir = BCMOLT_MSG_DIR_RESPONSE;
2438 bcmtrmux_control_to_host(device, msg);
2439
2440 /* Handle event */
2441 if (event != DEVICE_CONTROL_EVENT_NO_EVENT)
2442 {
2443 dev_ctrl_sm_call_state_cb(device, event, msg);
2444 }
2445}
2446
2447static void dev_ctrl_process_msg(bcmolt_devid device, bcmolt_msg *msg)
2448{
2449 if (msg->dir == BCMOLT_MSG_DIR_RESPONSE)
2450 {
2451 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_DEVICE_RECEIVED_ACK, msg);
2452 }
2453
2454 if (msg->group == BCMOLT_MGT_GROUP_AUTO)
2455 {
2456 if (msg->subgroup != BCMOLT_DEVICE_AUTO_ID_DEVICE_KEEP_ALIVE)
2457 {
2458 BCM_LOG(DEBUG, dev_ctrl_db[device].log_id, "Indication = %s (%d)\n", bcm_str_auto_id(msg->subgroup), msg->subgroup);
2459 }
2460
2461 switch (msg->subgroup)
2462 {
2463 case BCMOLT_DEVICE_AUTO_ID_DEVICE_KEEP_ALIVE:
2464 dev_ctrl_ka_rx_handler(device, (bcmolt_device_device_keep_alive *)msg);
2465 break;
2466 case BCMOLT_DEVICE_AUTO_ID_CONNECTION_FAILURE:
2467 /* note: this indication is not generated by the device - it's generated by device control itself */
2468 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_CONNECTION_FAILURE, msg);
2469 break;
2470 case BCMOLT_DEVICE_AUTO_ID_CONNECTION_ESTABLISHED:
2471 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_CONNECTION_ESTABLISHED, msg);
2472 break;
2473 case BCMOLT_DEVICE_AUTO_ID_DEVICE_READY:
2474 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_DEVICE_READY, msg);
2475 break;
2476 default:
2477 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Unexpected indication\n");
2478 break;
2479 }
2480 }
2481
2482 if (msg->group == BCMOLT_MGT_GROUP_OPER && msg->type == BCMOLT_MSG_TYPE_SET && msg->dir != BCMOLT_MSG_DIR_RESPONSE)
2483 {
2484 /* All operations happen entirely on the host side */
2485 handle_oper_set_msg(device, msg);
2486 }
2487
2488 if (msg->group == BCMOLT_MGT_GROUP_CFG && msg->dir != BCMOLT_MSG_DIR_RESPONSE)
2489 {
2490 dev_ctrl_db[device].last_message = msg;
2491 switch (msg->type)
2492 {
2493 case BCMOLT_MSG_TYPE_GET:
2494 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_DEVICE_CONFIG_GET, msg);
2495 break;
2496 case BCMOLT_MSG_TYPE_CLEAR:
2497 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_DEVICE_CLEAR, msg);
2498 break;
2499 case BCMOLT_MSG_TYPE_SET:
2500 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_DEVICE_CONFIG_SET, msg);
2501 break;
2502 default:
2503 break;
2504 }
2505 msg = NULL;
2506 }
2507
2508 if (msg != NULL)
2509 {
2510 bcmolt_msg_free(msg);
2511 }
2512}
2513
2514static bcmos_timer_rc dev_ctrl_connection_timer_handler(bcmos_timer *timer, long data)
2515{
2516 bcmolt_devid device = DEVICE_ID_FROM_MODULE_ID(timer->parm.owner);
2517
2518 if (dev_ctrl_db[device].device_params.state != BCMOLT_DEVICE_STATE_CONNECTING)
2519 {
2520 /* The timer is irrelevant in this state - discard it and return. */
2521 }
2522 else if (dev_ctrl_db[device].connection_info.state == DEV_CTRL_CONNECTING_STATE_CONFIGURING)
2523 {
2524 /* After we have sent the first "device configuration set" message to the device, the connection timer is used
2525 * for retransmitting this message in case the device missed it. */
2526 bcmolt_device_connection_established ind = {};
2527 BCMOLT_AUTO_INIT(&ind, device, connection_established);
2528 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_CONNECTION_ESTABLISHED, &ind.hdr.hdr);
2529 }
2530 else
2531 {
2532 /* Connection failure due to timeout. */
2533 bcmolt_device_connection_failure ind = {};
2534 BCMOLT_AUTO_INIT(&ind, device, connection_failure);
2535 ind.data.reason = BCMOLT_HOST_CONNECTION_FAIL_REASON_TIMEOUT;
2536 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_CONNECTION_FAILURE, &ind.hdr.hdr);
2537 }
2538
2539 return BCMOS_TIMER_STOP;
2540}
2541
2542#ifndef IN_BAND
2543static void dev_ctrl_get_ras_modes(bcmolt_system_mode system_mode, uint32_t *ras_0_mode, uint32_t *ras_1_mode)
2544{
2545 switch (system_mode)
2546 {
2547 case BCMOLT_SYSTEM_MODE_GPON__4_X:
2548 case BCMOLT_SYSTEM_MODE_GPON__8_X:
2549 *ras_0_mode = BCM_FLD_RAS_MODE_GPON;
2550 *ras_1_mode = BCM_FLD_RAS_MODE_NOT_CONFIGURED;
2551 break;
2552 case BCMOLT_SYSTEM_MODE_GPON__16_X:
2553 *ras_0_mode = BCM_FLD_RAS_MODE_GPON;
2554 *ras_1_mode = BCM_FLD_RAS_MODE_GPON;
2555 break;
2556 case BCMOLT_SYSTEM_MODE_XGPON_1__4_X:
2557 case BCMOLT_SYSTEM_MODE_XGPON_1__8_X:
2558 case BCMOLT_SYSTEM_MODE_NGPON2__8_X_2_P_5_G:
2559 *ras_0_mode = BCM_FLD_RAS_MODE_XGPON;
2560 *ras_1_mode = BCM_FLD_RAS_MODE_XGPON;
2561 break;
2562 case BCMOLT_SYSTEM_MODE_GPON_8_XGPON_4_X_COEXISTENCE:
2563 *ras_0_mode = BCM_FLD_RAS_MODE_XGPON;
2564 *ras_1_mode = BCM_FLD_RAS_MODE_GPON;
2565 break;
2566 case BCMOLT_SYSTEM_MODE_XGS__2_X_10_G:
2567 case BCMOLT_SYSTEM_MODE_NGPON2__2_X_10_G:
2568 *ras_0_mode = BCM_FLD_RAS_MODE_XGS_NGPON2;
2569 *ras_1_mode = BCM_FLD_RAS_MODE_XGS_NGPON2;
2570 break;
2571 default:
2572 *ras_0_mode = BCM_FLD_RAS_MODE_NOT_CONFIGURED;
2573 *ras_1_mode = BCM_FLD_RAS_MODE_NOT_CONFIGURED;
2574 break;
2575 }
2576}
2577
2578static bcmos_timer_rc dev_ctrl_boot_seq_timer_handler(bcmos_timer *timer, long data)
2579{
2580 bcmos_bool is_bootloader_done;
2581 bcmolt_devid device;
2582 uint32_t ras_0_mode;
2583 uint32_t ras_1_mode;
2584 bcmos_errno rc = BCM_ERR_OK;
2585 bcmos_timer_rc timer_rc = BCMOS_TIMER_STOP;
2586
2587 device = (bcmolt_devid)data;
2588
2589 if (dev_ctrl_db[device].boot_seq_info.polling_counter > 0)
2590 {
2591 dev_ctrl_db[device].boot_seq_info.polling_counter--;
2592 is_bootloader_done = bcm_fld_is_bootloader_done(device);
2593 if (is_bootloader_done)
2594 {
2595 /* Stop the boot timer */
2596 timer_rc = BCMOS_TIMER_STOP;
2597 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Boot loader phase done.\n");
2598
2599 if (dev_ctrl_db[device].device_params.debug.avs_control)
2600 {
2601 rc = bcm_fld_set_avs_cont(device, BCM_FLD_AVS_CONT); /* don't stop the cpu when avs fails. */
2602 }
2603 else
2604 {
2605 rc = bcm_fld_set_avs_cont(device, BCM_FLD_AVS_STOP); /* stop the cpu when avs fails. */
2606 }
2607 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_fld_set_avs_cont\n");
2608
2609 dev_ctrl_get_ras_modes(dev_ctrl_db[device].device_params.system_mode, &ras_0_mode, &ras_1_mode);
2610 rc = bcm_fld_set_ras_mode_set(device, 0, ras_0_mode);
2611 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_fld_set_ras_0_mode_set\n");
2612 rc = bcm_fld_set_ras_mode_set(device, 1, ras_1_mode);
2613 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcm_fld_set_ras_1_mode_set\n");
2614 rc = dev_ctrl_handle_application_image(device);
2615 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "dev_ctrl_handle_application_image()\n");
2616 }
2617 else
2618 {
2619 /* Restart the boot timer */
2620 timer_rc = BCMOS_TIMER_OK;
2621 }
2622 }
2623 else
2624 {
2625 timer_rc = BCMOS_TIMER_STOP;
2626 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "dev_ctrl_boot_seq timer expired while trying to burn BOOTLOADER\n");
2627 }
2628
2629 return timer_rc;
2630}
2631
2632static bcmos_timer_rc dev_ctrl_ddr_test_timer_handler(bcmos_timer *timer, long data)
2633{
2634 bcmos_bool is_ddr_test_done;
2635 bcmolt_devid device;
2636 bcmos_timer_rc timer_rc = BCMOS_TIMER_STOP;
2637
2638 device = (bcmolt_devid)data;
2639
2640 if (dev_ctrl_db[device].boot_seq_info.polling_counter > 0)
2641 {
2642 dev_ctrl_db[device].boot_seq_info.polling_counter--;
2643 is_ddr_test_done = bcm_fld_is_ddr_test_done(device);
2644 if (is_ddr_test_done)
2645 {
2646 /* Stop the boot timer */
2647 timer_rc = BCMOS_TIMER_STOP;
2648 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_DDR_TEST_COMPLETED, NULL);
2649 }
2650 else
2651 {
2652 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "Waiting for DDR Test %u\n", dev_ctrl_db[device].boot_seq_info.polling_counter);
2653 /* Restart the boot timer */
2654 timer_rc = BCMOS_TIMER_OK;
2655 }
2656 }
2657 else
2658 {
2659 timer_rc = BCMOS_TIMER_STOP;
2660 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_DDR_TEST_TIMEOUT, NULL);
2661 }
2662
2663 return timer_rc;
2664}
2665#endif
2666
2667static bcmos_errno dev_ctrl_init_modules(bcmolt_devid device)
2668{
2669 bcmos_module_parm module_params = {};
2670 bcmos_errno rc = BCM_ERR_OK;
2671 dev_ctrl_db[device].module_info.module_id = MODULE_ID_FROM_DEVICE_ID(device);
2672 snprintf(
2673 dev_ctrl_db[device].module_info.name,
2674 sizeof(dev_ctrl_db[device].module_info.name),
2675 "dev_ctrl%u_module",
2676 device);
2677 module_params.qparm.name = dev_ctrl_db[device].module_info.name;
2678 module_params.qparm.size = DEVICE_CONTROL_MSG_QUEUE_SIZE;
2679 module_params.init = NULL;
2680 rc = bcmos_module_create(
2681 dev_ctrl_db[device].module_info.module_id,
2682 &dev_ctrl_db[device].task_info.task,
2683 &module_params);
2684 if (rc != BCM_ERR_OK)
2685 {
2686 BCM_LOG(ERROR, dev_ctrl_db[device].log_id,
2687 "bcmos_module_create returned error %s (%d), module id %d\n",
2688 bcmos_strerror(rc),
2689 rc,
2690 dev_ctrl_db[device].module_info.module_id);
2691 }
2692 return rc;
2693}
2694
2695static bcmos_errno dev_ctrl_init_tasks(bcmolt_devid device)
2696{
2697 bcmos_task_parm task_params = {};
2698 bcmos_errno rc = BCM_ERR_OK;
2699 snprintf(dev_ctrl_db[device].task_info.name, sizeof(dev_ctrl_db[device].task_info.name), "dev_ctrl%u", device);
2700 task_params.name = dev_ctrl_db[device].task_info.name;
2701 task_params.priority = TASK_PRIORITY_DEVICE_CONTROL;
2702 task_params.core = BCMOS_CPU_CORE_ANY; /* No CPU affinity */
2703 task_params.init_handler = NULL;
2704 task_params.data = (long)device;
2705 rc = bcmos_task_create(&dev_ctrl_db[device].task_info.task, &task_params);
2706 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcmos_task_create()\n");
2707
2708 return rc;
2709}
2710
2711static void dev_ctrl_mod_msg_handler(bcmos_module_id module_id, bcmos_msg *os_msg)
2712{
2713 bcmolt_msg *msg;
2714 bcmolt_devid device;
2715
2716 device = DEVICE_ID_FROM_MODULE_ID(module_id);
2717 msg = os_msg->data;
2718
2719#ifndef IN_BAND
2720#ifdef ENABLE_LOG
2721 if (msg->obj_type == BCMOLT_OBJ_ID_LOGGER &&
2722 msg->group == BCMOLT_MGT_GROUP_CFG &&
2723 msg->type == BCMOLT_MSG_TYPE_GET &&
2724 !dev_ctrl_is_connected(dev_ctrl_db[device].device_params.state))
2725 {
2726 /* The device is not ready, but still we can fetch the logger file from SRAM. */
2727 msg->err = dev_ctrl_get_dev_log(device, (bcmolt_logger_cfg *)msg);
2728 msg->dir = BCMOLT_MSG_DIR_RESPONSE;
2729 bcmtrmux_control_to_host(device, msg);
2730 bcmolt_msg_free(msg);
2731 return;
2732 }
2733#endif
2734
2735 if (msg->obj_type == BCMOLT_OBJ_ID_SOFTWARE_ERROR &&
2736 msg->group == BCMOLT_MGT_GROUP_CFG &&
2737 (msg->type == BCMOLT_MSG_TYPE_GET || msg->type == BCMOLT_MSG_TYPE_GET_MULTI) &&
2738 !dev_ctrl_is_connected(dev_ctrl_db[device].device_params.state))
2739 {
2740 /* get sw error table from SRAM */
2741 msg->err = dev_ctrl_sw_error_get(device, msg);
2742 msg->dir = BCMOLT_MSG_DIR_RESPONSE;
2743 bcmtrmux_control_to_host(device, msg);
2744 bcmolt_msg_free(msg);
2745 return;
2746 }
2747#endif
2748
2749 if (msg->obj_type == BCMOLT_OBJ_ID_DEBUG)
2750 {
2751 bcmolt_debug_ctrl_process_msg(device, msg, dev_ctrl_is_connected(dev_ctrl_db[device].device_params.state));
2752 return;
2753 }
2754
2755 if (msg->obj_type != BCMOLT_OBJ_ID_DEVICE)
2756 {
2757 bcmolt_msg_err(
2758 msg,
2759 DEV_LOG_INVALID_ID,
2760 BCM_ERR_INTERNAL,
2761 BCMOLT_ERR_FIELD_NONE,
2762 "Can't access target when disconnected");
2763 msg->dir = BCMOLT_MSG_DIR_RESPONSE;
2764 bcmtrmux_control_to_host(device, msg);
2765 bcmolt_msg_free(msg);
2766 }
2767 else if (msg->group == BCMOLT_MGT_GROUP_AUTO)
2768 {
2769 dev_ctrl_process_msg(device, msg);
2770 }
2771 else if (msg->dir == BCMOLT_MSG_DIR_RESPONSE)
2772 {
2773 if (msg->group == BCMOLT_MGT_GROUP_OPER && msg->subgroup == BCMOLT_DEVICE_OPER_ID_HOST_KEEP_ALIVE)
2774 {
2775 /* Just free it, otherwise ignore keepalive oper responses */
2776 bcmolt_msg_free(msg);
2777 }
2778 else if ((dev_ctrl_db[device].device_params.state == BCMOLT_DEVICE_STATE_WAITING_FOR_DEVICE) || (dev_ctrl_db[device].device_params.state == BCMOLT_DEVICE_STATE_CONNECTING))
2779 {
2780 dev_ctrl_process_msg(device, msg);
2781 }
2782 else
2783 {
2784 BCM_LOG(INFO, dev_ctrl_db[device].log_id, "received unexpected response: group=%u subgroup=%u\n", msg->group, msg->subgroup);
2785 bcmolt_msg_free(msg);
2786 }
2787 }
2788 else if (dev_ctrl_db[device].device_params.state != BCMOLT_DEVICE_STATE_CONNECTING)
2789 {
2790 msg->err = dev_ctrl_validate_msg(device, msg);
2791 if (msg->err == BCM_ERR_OK)
2792 {
2793 dev_ctrl_process_msg(device, msg);
2794 }
2795 else
2796 {
2797 msg->dir = BCMOLT_MSG_DIR_RESPONSE;
2798 bcmtrmux_control_to_host(device, msg);
2799 bcmolt_msg_free(msg);
2800 }
2801 }
2802 else
2803 {
2804 bcmolt_msg_err(msg, DEV_LOG_INVALID_ID, BCM_ERR_STATE, BCMOLT_ERR_FIELD_NONE, "Device is busy");
2805 msg->dir = BCMOLT_MSG_DIR_RESPONSE;
2806 bcmtrmux_control_to_host(device, msg);
2807 bcmolt_msg_free(msg);
2808 }
2809}
2810
2811static void dev_ctrl_mod_msg_release(bcmos_msg *os_msg)
2812{
2813 bcmolt_msg_free(container_of(os_msg, bcmolt_msg, os_msg));
2814}
2815
2816static bcmos_msg dev_ctrl_ipc_msg = { .handler = dev_ctrl_mod_msg_handler, .release = dev_ctrl_mod_msg_release };
2817
2818static void bcmdev_rx_handler(bcmolt_devid device, bcmolt_msg *msg, void *data)
2819{
2820 bcmos_errno rc;
2821
2822 msg->os_msg = dev_ctrl_ipc_msg;
2823 msg->os_msg.data = msg;
2824 rc = bcmos_msg_send_to_module(dev_ctrl_db[device].module_info.module_id, &msg->os_msg, BCMOS_MSG_SEND_AUTO_FREE);
2825 if (rc != BCM_ERR_OK)
2826 {
2827 BCM_LOG(ERROR, dev_ctrl_db[device].log_id,
2828 "bcmos_msg_send_to_module returned error %s (%d), module id %d\n",
2829 bcmos_strerror(rc),
2830 rc,
2831 dev_ctrl_db[device].module_info.module_id);
2832 }
2833}
2834
2835#ifndef IN_BAND
2836static bcmos_timer_rc exception_monitor_timer_handler(bcmos_timer *timer, long data)
2837{
2838 bcmolt_devid device = (bcmolt_devid)data;
2839 bcmos_errno rc;
2840
2841 if (!dev_ctrl_is_connected(dev_ctrl_db[device].device_params.state))
2842 {
2843 return BCM_ERR_OK; /* in case this happens during a disconnect/reset operation */
2844 }
2845
2846 rc = dev_ctrl_get_exception_log_if_present(device);
2847 if (rc != BCM_ERR_OK && rc != BCM_ERR_NOENT)
2848 {
2849 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "cant read Exception log for device %d error %s (%d)\n", device, bcmos_strerror(rc), rc);
2850 }
2851 return BCMOS_TIMER_OK;
2852}
2853#endif
2854
2855static bcmos_timer_rc device_response_timer_handler(bcmos_timer *timer, long data)
2856{
2857 bcmolt_devid device = (bcmolt_devid)data;
2858 dev_ctrl_sm_call_state_cb(device, DEVICE_CONTROL_EVENT_DEVICE_TIMER_TIMEOUT, NULL);
2859 return BCMOS_TIMER_OK;
2860}
2861
2862static bcmos_timer_rc reset_delay_timer_handler(bcmos_timer *timer, long data)
2863{
2864 bcmos_errno rc = dev_ctrl_params.host_reset_cb();
2865 if (rc != BCM_ERR_OK)
2866 {
2867 BCM_LOG(ERROR, dev_ctrl_db[(bcmolt_devid)data].log_id, "Host reset callback failed: %s (%d)\n", bcmos_strerror(rc), rc);
2868 }
2869 return BCMOS_TIMER_OK;
2870}
2871
2872static bcmos_errno dev_ctrl_timer_create(
2873 bcmolt_devid device,
2874 bcmos_module_id module_id,
2875 dev_ctrl_timer *timer,
2876 const char *name,
2877 bcmos_bool periodic,
2878 F_bcmos_timer_handler handler)
2879{
2880 bcmos_timer_parm timer_params = {};
2881 bcmos_errno rc = BCM_ERR_OK;
2882
2883 snprintf(timer->name, sizeof(timer->name), "dev_ctrl_%s_timer%u", name, device);
2884 timer_params.name = timer->name;
2885 timer_params.owner = module_id;
2886 timer_params.periodic = periodic;
2887 timer_params.handler = handler;
2888 timer_params.data = device;
2889 rc = bcmos_timer_create(&timer->timer, &timer_params);
2890 if (rc != BCM_ERR_OK)
2891 {
2892 BCM_LOG(ERROR, dev_ctrl_db[device].log_id,
2893 "'%s' timer creation failed, bcmos_timer_create returned error %s (%d)\n",
2894 timer->name,
2895 bcmos_strerror(rc),
2896 rc);
2897 }
2898
2899 return rc;
2900}
2901
2902#ifndef IN_BAND
2903static void dev_ctrl_link_up_down_cb(uint8_t dev_id, bcm_ll_pcie_link_status status)
2904{
2905 BCM_LOG(INFO, dev_ctrl_db[dev_id].log_id, "Device %u: PCIe link %s\n", dev_id, status == BCM_LL_PCIE_LINK_DOWN ? "down" : "up");
2906}
2907#endif
2908
2909static bcmtrmux_msg_dest dev_ctrl_msg_filter_cb(
2910 bcmolt_devid device,
2911 bcmolt_obj_id obj,
2912 bcmolt_mgt_group group,
2913 uint16_t subgroup)
2914{
2915 /* Device control should intercept the message if one of the two happens:
2916 * 1. The message object is "device".
2917 * 2. The message object is not "device", but the device is not ready, so an appropriate error should be returned to
2918 * the host application. */
2919 bcmtrmux_msg_dest dest = BCMTRMUX_DEST_REMOTE;
2920
2921 if (!dev_ctrl_is_connected(dev_ctrl_db[device].device_params.state))
2922 {
2923 dest = BCMTRMUX_DEST_LOCAL;
2924 }
2925 else if (obj == BCMOLT_OBJ_ID_DEBUG)
2926 {
2927 dest = BCMTRMUX_DEST_LOCAL;
2928 }
2929 else if (obj == BCMOLT_OBJ_ID_DEVICE)
2930 {
2931 switch (group)
2932 {
2933 case BCMOLT_MGT_GROUP_OPER:
2934 switch (subgroup)
2935 {
2936 case BCMOLT_DEVICE_OPER_ID_IMAGE_TRANSFER_START:
2937 case BCMOLT_DEVICE_OPER_ID_IMAGE_TRANSFER_DATA:
2938 case BCMOLT_DEVICE_OPER_ID_SW_UPGRADE_ACTIVATE:
2939 return BCMTRMUX_DEST_REMOTE;
2940 default:
2941 return BCMTRMUX_DEST_LOCAL;
2942 }
2943 break;
2944 default:
2945 return BCMTRMUX_DEST_LOCAL;
2946 }
2947 }
2948 return dest;
2949}
2950
2951static void dev_ctrl_init_device_objects(bcmolt_devid device)
2952{
2953 dev_ctrl_clear_device_cfg(device);
2954 dev_ctrl_init_connection_state(device);
2955 dev_ctrl_db[device].device_params.state = BCMOLT_DEVICE_STATE_DISCONNECTED;
2956 dev_ctrl_db[device].device_params.system_mode = BCMOLT_SYSTEM_MODE__NUM_OF;
2957 dev_ctrl_db[device].boot_seq_info.polling_counter = BOOT_SEQ_POLLING_MAX_NUMBER;
2958 dev_ctrl_db[device].boot_seq_info.polling_interval = BOOT_SEQ_POLL_INTERVAL_SEC * BCMOS_MICROSECONDS_IN_SECONDS;
2959 dev_ctrl_db[device].corr_tag = 0;
2960#ifdef ENABLE_LOG
2961 dev_ctrl_db[device].sram_log_offset = 0;
2962 dev_ctrl_db[device].msgs_read = 0;
2963#endif
2964
2965#ifndef SIMULATION_BUILD
2966 dev_ctrl_db[device].trx_disable_mask = 0xFFFF; /* Mark all PONs with TRX disabled. */
2967#endif
2968
2969 dev_ctrl_db[device].conn_fail_reason = BCMOLT_HOST_CONNECTION_FAIL_REASON_NONE;
2970 dev_ctrl_db[device].last_event = DEVICE_CONTROL_EVENT_NO_EVENT;
2971}
2972
2973bcmos_errno bcmolt_dev_ctrl_host_event_write(uint32_t device, uint32_t event)
2974{
2975#ifndef IN_BAND
2976 bcmolt_device_state state = dev_ctrl_db[device].device_params.state;
2977#endif
2978#ifndef SIMULATION_BUILD
2979 /* Update local database, so that after reset we will be able to sync this value with the device. */
2980 dev_ctrl_db[device].trx_disable_mask = event;
2981#endif
2982#ifndef IN_BAND
2983 /* Notify device using SRAM, but only if we are already connected (otherwise FLD might be not ready). */
2984 if (dev_ctrl_is_connected(state))
2985 bcm_fld_set_host_event(device, event);
2986#endif
2987 return BCM_ERR_OK;
2988}
2989/*Use different function signatures linux kernel device control and other*/
2990#if !defined(LINUX_USER_SPACE)
2991bcmos_errno bcmolt_dev_ctrl_init(bcmolt_dev_ctrl_params *params)
2992#else
2993bcmos_errno bcmolt_dev_ctrl_init()
2994#endif
2995{
2996 bcmolt_devid device;
2997 bcmos_errno rc = BCM_ERR_OK;
2998
2999#if !defined(LINUX_USER_SPACE)
3000 if (!params->system_mode_validate_cb ||
3001 !params->image_read_cb ||
3002 !params->device_off_cb ||
3003 !params->device_on_cb ||
3004 !params->device_is_running_cb ||
3005 !params->host_reset_cb ||
3006 !params->pcie_channel_prepare_cb ||
3007 !params->pcie_channel_remove_cb)
3008 {
3009 BCMOS_TRACE_ERR("Missing required callbacks\n");
3010 return BCM_ERR_PARM;
3011 }
3012
3013 dev_ctrl_params = *params;
3014#endif
3015 rc = bcmtrmux_init(dev_ctrl_msg_filter_cb);
3016 BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcmtrmux_init()\n");
3017
3018#ifndef IN_BAND
3019 rc = bcm_fld_init(BCMTR_MAX_OLTS);
3020 BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_fld_init()\n");
3021#endif
3022
3023 for (device = 0; device < BCMTR_MAX_OLTS; device++)
3024 {
3025#ifdef ENABLE_LOG
3026 char log_name[MAX_DEV_LOG_ID_NAME];
3027 snprintf(log_name, sizeof(log_name) - 1, "dev_ctrl_%u", device);
3028 dev_ctrl_db[device].log_id = bcm_dev_log_id_register(log_name, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
3029#endif
3030 dev_ctrl_init_device_objects(device);
3031 image_buf[device] = bcmos_alloc(IMAGE_BUF_SIZE);
3032 if (!image_buf[device])
3033 {
3034 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Can't allocate packet buffer\n");
3035 return BCM_ERR_NOMEM;
3036 }
3037 rd_image_buf[device] = bcmos_alloc(IMAGE_BUF_SIZE);
3038 if (!rd_image_buf[device])
3039 {
3040 BCM_LOG(ERROR, dev_ctrl_db[device].log_id, "Can't allocate nh_packet buffer\n");
3041 return BCM_ERR_NOMEM;
3042 }
3043 rc = dev_ctrl_init_tasks(device);
3044 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "dev_ctrl_init_tasks()\n");
3045
3046 rc = dev_ctrl_init_modules(device);
3047 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "dev_ctrl_init_modules()\n");
3048
3049 dev_ctrl_db[device].ka_info.orig = BCM_KEEP_ALIVE_MSG_ORIG_HOST;
3050 dev_ctrl_db[device].ka_info.send_handler = dev_ctrl_ka_tx_handler;
3051 dev_ctrl_db[device].ka_info.disconnect_handler = dev_ctrl_ka_disconnect_handler;
3052 dev_ctrl_db[device].ka_info.device = device;
3053 rc = create_keep_alive_timer(&dev_ctrl_db[device].ka_info, dev_ctrl_db[device].module_info.module_id);
3054 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "create_keep_alive_timer()\n");
3055
3056 rc = dev_ctrl_timer_create(
3057 device,
3058 dev_ctrl_db[device].module_info.module_id,
3059 &dev_ctrl_db[device].connection_info.timer,
3060 "connection",
3061 BCMOS_FALSE, /* non-periodic */
3062 dev_ctrl_connection_timer_handler);
3063 BCMOS_CHECK_RETURN_ERROR(rc, rc);
3064
3065#ifndef IN_BAND
3066 rc = dev_ctrl_timer_create(
3067 device,
3068 dev_ctrl_db[device].module_info.module_id,
3069 &dev_ctrl_db[device].boot_seq_info.timer,
3070 "boot_seq",
3071 BCMOS_TRUE, /* periodic */
3072 dev_ctrl_boot_seq_timer_handler);
3073 BCMOS_CHECK_RETURN_ERROR(rc, rc);
3074
3075 rc = dev_ctrl_timer_create(
3076 device,
3077 dev_ctrl_db[device].module_info.module_id,
3078 &dev_ctrl_db[device].exception_monitor_timer,
3079 "exception_monitor",
3080 BCMOS_TRUE, /* periodic */
3081 exception_monitor_timer_handler);
3082 BCMOS_CHECK_RETURN_ERROR(rc, rc);
3083#endif
3084 rc = dev_ctrl_timer_create(
3085 device,
3086 dev_ctrl_db[device].module_info.module_id,
3087 &dev_ctrl_db[device].device_response_timer,
3088 "device_response",
3089 BCMOS_FALSE, /* non-periodic */
3090 device_response_timer_handler);
3091 BCMOS_CHECK_RETURN_ERROR(rc, rc);
3092
3093 rc = dev_ctrl_timer_create(
3094 device,
3095 dev_ctrl_db[device].module_info.module_id,
3096 &dev_ctrl_db[device].reset_delay_timer,
3097 "reset_delay",
3098 BCMOS_FALSE, /* non-periodic */
3099 reset_delay_timer_handler);
3100 BCMOS_CHECK_RETURN_ERROR(rc, rc);
3101
3102 /* Register callback to MUX */
3103 rc = bcmtrmux_local_handler_register(device, bcmdev_rx_handler, (void *)(long)device);
3104 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcmtrmux_local_handler_register()\n");
3105
3106 /* Intercept CONNECTION_ESTABLISHED, DEVICE_READY, KEEP_ALIVE messages */
3107 rc = bcmtrmux_control_auto_intercept_filter(
3108 device,
3109 BCMOLT_OBJ_ID_DEVICE,
3110 BCMOLT_DEVICE_AUTO_ID_CONNECTION_ESTABLISHED);
3111 rc = rc ? rc : bcmtrmux_control_auto_intercept_filter(
3112 device,
3113 BCMOLT_OBJ_ID_DEVICE,
3114 BCMOLT_DEVICE_AUTO_ID_DEVICE_READY);
3115 rc = rc ? rc : bcmtrmux_control_auto_intercept_filter(
3116 device,
3117 BCMOLT_OBJ_ID_DEVICE,
3118 BCMOLT_DEVICE_AUTO_ID_DEVICE_KEEP_ALIVE);
3119 BCM_DEV_CTRL_RETURN_ON_ERROR(device, rc, "bcmtrmux_control_auto_intercept_filter()\n");
3120 }
3121#ifndef IN_BAND
3122 /* Register for link_up / link_down interrupt */
3123 bcm_ll_pcie_status_change_register(dev_ctrl_link_up_down_cb);
3124#endif
3125
3126 bcmolt_debug_ctrl_init();
3127
3128 return rc;
3129}
3130
3131void bcmolt_dev_ctrl_exit(void)
3132{
3133#ifndef IN_BAND
3134 bcmolt_devid device;
3135
3136 for (device = 0; device < BCMTR_MAX_OLTS; device++)
3137 {
3138 bcmtrmux_local_handler_unregister(device);
3139 bcmos_free(image_buf[device]);
3140 bcmos_free(rd_image_buf[device]);
3141 bcmos_timer_destroy(&dev_ctrl_db[device].connection_info.timer.timer);
3142 bcmos_timer_destroy(&dev_ctrl_db[device].ka_info.ka_timer.timer);
3143 bcmos_timer_destroy(&dev_ctrl_db[device].boot_seq_info.timer.timer);
3144 bcmos_timer_destroy(&dev_ctrl_db[device].exception_monitor_timer.timer);
3145 bcmos_timer_destroy(&dev_ctrl_db[device].device_response_timer.timer);
3146 bcmos_timer_destroy(&dev_ctrl_db[device].reset_delay_timer.timer);
3147 bcmos_module_destroy(dev_ctrl_db[device].module_info.module_id);
3148 bcmos_task_destroy(&dev_ctrl_db[device].task_info.task);
3149 }
3150#endif
3151#ifndef IN_BAND
3152 bcm_fld_exit();
3153#endif
3154 bcmtrmux_exit();
3155#ifndef IN_BAND
3156 bcm_ll_pcie_status_change_unregister();
3157#endif
3158}