BAL and Maple Release 2.2
Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bcm68620_release/release/host_driver/keep_alive/Makefile b/bcm68620_release/release/host_driver/keep_alive/Makefile
new file mode 100644
index 0000000..ee02f1a
--- /dev/null
+++ b/bcm68620_release/release/host_driver/keep_alive/Makefile
@@ -0,0 +1,20 @@
+# Common keep_alive
+#
+MOD_NAME = keep_alive
+
+ifeq ("$(OS_KERNEL)", "linux")
+MOD_TYPE = linux_lib
+else
+MOD_TYPE = lib
+endif
+
+MOD_DEPS = model
+
+srcs = bcm_keep_alive.c
+
+# If called by linux kernel builder - add include paths manually.
+# It is not elegant, but we'll not have many linux modules
+ifneq ("$(KBUILD_SRC)", "")
+ -include $(OUT_DIR_BASE)/Makefile.config.$(MOD_NAME)
+endif
+USE_LINT = yes
diff --git a/bcm68620_release/release/host_driver/keep_alive/bcm_keep_alive.c b/bcm68620_release/release/host_driver/keep_alive/bcm_keep_alive.c
new file mode 100644
index 0000000..780f60e
--- /dev/null
+++ b/bcm68620_release/release/host_driver/keep_alive/bcm_keep_alive.c
@@ -0,0 +1,245 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and
+ to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#include <bcmos_system.h>
+#include <bcmolt_msg.h>
+#include <bcmolt_api.h>
+#include <bcmolt_model_types.h>
+#include <bcmolt_model_ids.h>
+#include "bcm_keep_alive.h"
+
+keep_alive_msg_orig2str_t keep_alive_msg_orig2str[] =
+{
+ {BCM_KEEP_ALIVE_MSG_ORIG_DEVICE, "device"},
+ {BCM_KEEP_ALIVE_MSG_ORIG_HOST, "host"},
+ {-1}
+};
+
+static void keep_alive_tx_handler(bcmos_keep_alive_info *ka_info);
+
+static bcmos_timer_rc keep_alive_timer_handler(bcmos_timer *timer, long data)
+{
+ bcmos_keep_alive_info *ka_info;
+ uint32_t last_recv_ka_ts;
+ uint32_t ka_interval;
+ uint32_t ka_tolerance;
+ uint32_t time_diff_from_prev_ka;
+ uint32_t ka_process_start_ts;
+ uint32_t prev_ka_ts;
+ ka_info = (bcmos_keep_alive_info *)data;
+ last_recv_ka_ts = ka_info->last_recv_ka_timestamp;
+ ka_interval = ka_info->ka_interval;
+ ka_tolerance = ka_info->ka_tolerance;
+ ka_process_start_ts = ka_info->ka_process_start_ts;
+
+ /* The first keep alive message that arrives changes last_recv_ka_ts to a value different than zero.
+ * If no keep alive message has arrived yet then the previous keep alive time stamp is the time the process has
+ * started. */
+ prev_ka_ts = (last_recv_ka_ts ? last_recv_ka_ts : ka_process_start_ts);
+
+ /* Time difference between current time and the previous keep alive message */
+ time_diff_from_prev_ka = bcmos_timestamp() - prev_ka_ts;
+
+ /* Check if keep alive message has been received in the past keep alive interval, both part of the equation can't overflow:
+ * The left part is subtraction of two unsigned integers and the right part is restricted by ka_interval max value and ka_tolerance max value -
+ * their multiplication can't exceed max unsigned integer */
+ if (time_diff_from_prev_ka > ka_interval * (ka_tolerance + 1))
+ {
+ if (last_recv_ka_ts)
+ {
+ BCMOS_TRACE_INFO(
+ "Didn't receive keep alive message for %u seconds - about to disconnect\n",
+ (bcmos_timestamp() - last_recv_ka_ts) / BCMOS_MICROSECONDS_IN_SECONDS);
+ }
+ else
+ {
+ BCMOS_TRACE_INFO(
+ "Didn't receive keep alive message since keep alive process started %u seconds ago - "
+ "about to disconnect\n",
+ (bcmos_timestamp() - ka_process_start_ts) / BCMOS_MICROSECONDS_IN_SECONDS);
+ }
+
+ if (ka_info->disconnect_handler(ka_info->device) != BCM_ERR_OK)
+ {
+ if (ka_info->orig == BCM_KEEP_ALIVE_MSG_ORIG_HOST)
+ BCMOS_TRACE_ERR("Error while trying to send disconnect message (device=%d)\n", ka_info->device);
+ else
+ BCMOS_TRACE_ERR("Error while trying to invoke disconnect from the host procedure\n");
+ }
+ return BCMOS_TIMER_STOP;
+ }
+
+ /* Send Keep alive message to the remote side */
+ keep_alive_tx_handler(ka_info);
+
+ return BCMOS_TIMER_OK;
+}
+
+static void keep_alive_tx_handler(bcmos_keep_alive_info *ka_info)
+{
+ bcmos_keep_alive_msg ka_msg = {};
+ bcmolt_device_key key = {};
+ if (ka_info->orig == BCM_KEEP_ALIVE_MSG_ORIG_HOST)
+ {
+ BCMOLT_OPER_INIT(&ka_msg.host, device, host_keep_alive, key);
+ ka_msg.host.hdr.hdr.type = BCMOLT_MSG_TYPE_SET;
+ BCMOLT_OPER_PROP_SET(&ka_msg.host, device, host_keep_alive, sequence_number, ka_info->last_sent_ka_seq++);
+ BCMOLT_OPER_PROP_SET(&ka_msg.host, device, host_keep_alive, time_stamp, bcmos_timestamp());
+ }
+ else
+ {
+ BCMOLT_AUTO_INIT(&ka_msg.device, device, device_keep_alive);
+ ka_msg.device.hdr.hdr.type = BCMOLT_MSG_TYPE_SET;
+ ka_msg.device.data.sequence_number = ka_info->last_sent_ka_seq++;
+ ka_msg.device.data.time_stamp = bcmos_timestamp();
+ }
+
+ if (ka_info->send_handler(ka_info->device, (bcmolt_msg *)&ka_msg) != BCM_ERR_OK)
+ {
+ BCMOS_TRACE_INFO("Error while trying to send keep alive sequence number %u\n", ka_info->last_sent_ka_seq);
+ }
+}
+
+void keep_alive_rx_handler(const bcmos_keep_alive_data_msg *ka_data_msg, bcmos_keep_alive_info *ka_info)
+{
+ uint32_t seq_diff;
+ uint32_t rx_msg_seq;
+ uint32_t rx_msg_ts;
+
+ /* Tricky part - rx_msg_seq is NOT from the originator but from the other side */
+ if (ka_info->orig == BCM_KEEP_ALIVE_MSG_ORIG_HOST)
+ {
+ rx_msg_seq = ka_data_msg->device.sequence_number;
+ rx_msg_ts = ka_data_msg->device.time_stamp;
+ }
+ else
+ {
+ rx_msg_seq = ka_data_msg->host.sequence_number;
+ rx_msg_ts = ka_data_msg->host.time_stamp;
+ }
+
+ /* If last_recv_ka_seq and last_recv_ka_timestamp are both zeros then it's the first message */
+ if (ka_info->last_recv_ka_seq || ka_info->last_recv_ka_timestamp)
+ {
+ /* All part of the equation are unsigned integers so warp around is already taken care of */
+ seq_diff = rx_msg_seq - ka_info->last_recv_ka_seq;
+
+ /* In the normal case seq_diff should be one */
+ if (seq_diff > 1UL)
+ {
+ BCMOS_TRACE_INFO(
+ "Current keep alive sequence number is %u while previous keep alive sequence number was %u\n",
+ rx_msg_seq,
+ ka_info->last_recv_ka_seq);
+ BCMOS_TRACE_INFO(
+ "Current time stamp is %u while previous time stamp was %u, receive timestamp is %u\n",
+ bcmos_timestamp(),
+ ka_info->last_recv_ka_timestamp,rx_msg_ts);
+ if (seq_diff <= ka_info->ka_tolerance)
+ {
+ BCMOS_TRACE_INFO(
+ "Missed %u keep alive messages (keep alive tolerance is to lose %d messages)\n",
+ seq_diff,
+ ka_info->ka_tolerance);
+ }
+ else
+ {
+ BCMOS_TRACE_ERR(
+ "Missed %u keep alive messages (keep alive tolerance is to lose %d messages - "
+ "about to disconnect)\n",
+ seq_diff,
+ ka_info->ka_tolerance);
+ stop_keep_alive_process(ka_info);
+ if (ka_info->disconnect_handler(ka_info->device) != BCM_ERR_OK)
+ {
+ if (ka_info->orig == BCM_KEEP_ALIVE_MSG_ORIG_HOST)
+ {
+ BCMOS_TRACE_ERR(
+ "Error while trying to send disconnect message (device=%d)\n",
+ ka_info->device);
+ }
+ else
+ {
+ BCMOS_TRACE_ERR("Error while trying to send disconnect from the host message\n");
+ }
+ }
+ }
+ }
+ }
+ /* Stroe at the recieving side's database, the sequence number of the last message that came */
+ ka_info->last_recv_ka_seq = rx_msg_seq;
+
+ /* The time stamp is taken from the clock at the receiving side , not what came in the message */
+ ka_info->last_recv_ka_timestamp = bcmos_timestamp();
+}
+
+bcmos_errno create_keep_alive_timer(bcmos_keep_alive_info *ka_info, bcmos_module_id module_id)
+{
+ bcmos_timer_parm timer_params = {};
+ bcmos_errno rc = BCM_ERR_OK;
+ ka_info->last_recv_ka_timestamp = 0;
+ ka_info->last_recv_ka_seq = 0;
+
+ snprintf(ka_info->ka_timer.name, sizeof(ka_info->ka_timer.name), "keep_alive_t%u", ka_info->device);
+ timer_params.name = ka_info->ka_timer.name;
+ timer_params.owner = module_id;
+ timer_params.periodic = BCMOS_TRUE;
+ timer_params.handler = keep_alive_timer_handler;
+ timer_params.data = (long)ka_info;
+ rc = bcmos_timer_create(&ka_info->ka_timer.timer, &timer_params);
+ if (rc != BCM_ERR_OK)
+ {
+ BCMOS_TRACE_ERR(
+ "keep alive timer creation failed, bcmos_timer_create returned error %s (%d)\n",
+ bcmos_strerror(rc),
+ rc);
+ }
+ return rc;
+}
+
+void start_keep_alive_process(bcmos_keep_alive_info *ka_info)
+{
+ ka_info->last_recv_ka_timestamp = 0;
+ ka_info->last_recv_ka_seq = 0;
+ ka_info->ka_process_start_ts = bcmos_timestamp();
+ bcmos_timer_start(&ka_info->ka_timer.timer, ka_info->ka_interval);
+}
+
+void stop_keep_alive_process(bcmos_keep_alive_info *ka_info)
+{
+ bcmos_timer_stop(&ka_info->ka_timer.timer);
+}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(create_keep_alive_timer);
+EXPORT_SYMBOL(keep_alive_rx_handler);
+
+MODULE_DESCRIPTION("BCM device keep-alive support");
+MODULE_LICENSE("Dual BSD/GPL");
+#endif
diff --git a/bcm68620_release/release/host_driver/keep_alive/bcm_keep_alive.h b/bcm68620_release/release/host_driver/keep_alive/bcm_keep_alive.h
new file mode 100644
index 0000000..3779ddd
--- /dev/null
+++ b/bcm68620_release/release/host_driver/keep_alive/bcm_keep_alive.h
@@ -0,0 +1,86 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and
+ to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#ifndef BCM_KEEP_ALIVE_H_
+#define BCM_KEEP_ALIVE_H_
+
+#include <bcmos_system.h>
+#include <bcmolt_conv.h>
+
+/* Message originator : device or host */
+typedef enum
+{
+ BCM_KEEP_ALIVE_MSG_ORIG_DEVICE,
+ BCM_KEEP_ALIVE_MSG_ORIG_HOST,
+} keep_alive_msg_orig;
+
+typedef struct
+{
+ char name[MAX_TIMER_NAME_SIZE];
+ bcmos_timer timer;
+} keep_alive_timer;
+
+typedef bcmos_errno (*F_bcmos_keep_alive_send_handler)(bcmolt_devid device, bcmolt_msg *msg);
+typedef bcmos_errno (*F_bcmos_keep_alive_disconnect_handler)(bcmolt_devid device);
+
+typedef struct
+{
+ uint32_t last_sent_ka_seq;
+ uint32_t last_recv_ka_seq;
+ uint32_t last_recv_ka_timestamp;
+ uint32_t ka_process_start_ts;
+ uint32_t ka_interval;
+ uint32_t ka_tolerance;
+ keep_alive_msg_orig orig;
+ bcmolt_devid device;
+ keep_alive_timer ka_timer;
+ F_bcmos_keep_alive_disconnect_handler disconnect_handler;
+ F_bcmos_keep_alive_send_handler send_handler;
+} bcmos_keep_alive_info;
+
+typedef union
+{
+ bcmolt_device_device_keep_alive device; /**< Keep alive message originated at the Device */
+ bcmolt_device_host_keep_alive host; /**< Keep alive message originated at the Host */
+} bcmos_keep_alive_msg;
+
+typedef union
+{
+ bcmolt_device_device_keep_alive_data device; /**< Keep alive message originated at the Device */
+ bcmolt_device_host_keep_alive_data host; /**< Keep alive message originated at the Host */
+} bcmos_keep_alive_data_msg;
+
+BCMOLT_TYPE2STR(keep_alive_msg_orig, extern)
+
+void keep_alive_rx_handler(const bcmos_keep_alive_data_msg *ka_data_msg, bcmos_keep_alive_info *ka_info);
+bcmos_errno create_keep_alive_timer(bcmos_keep_alive_info *ka_info,bcmos_module_id module_id);
+void start_keep_alive_process(bcmos_keep_alive_info *ka_info);
+void stop_keep_alive_process(bcmos_keep_alive_info *ka_info);
+
+#endif /* BCM_KEEP_ALIVE_H_ */
diff --git a/bcm68620_release/release/host_driver/keep_alive/daemon/Makefile b/bcm68620_release/release/host_driver/keep_alive/daemon/Makefile
new file mode 100755
index 0000000..5eb7f6c
--- /dev/null
+++ b/bcm68620_release/release/host_driver/keep_alive/daemon/Makefile
@@ -0,0 +1,11 @@
+# Common keep_alive
+#
+MOD_NAME = keep_alive_daemon
+
+MOD_TYPE = lib
+
+MOD_DEPS = model
+
+srcs = ../bcm_keep_alive.c
+
+USE_LINT = yes