[qca-nss-drv] Added interface for unaligned trap statistics.

Change-Id: I4b3bbdc78ccc2bda908bd87fbe843ea8ae220c79
Signed-off-by: Jackson Bockus <jbockus@codeaurora.org>
diff --git a/Makefile b/Makefile
index b931364..ee4273c 100644
--- a/Makefile
+++ b/Makefile
@@ -104,6 +104,9 @@
 			nss_tunipip6.o \
 			nss_tunipip6_log.o \
 			nss_tx_msg_sync.o \
+			nss_unaligned.o \
+			nss_unaligned_log.o \
+			nss_unaligned_stats.o \
 			nss_virt_if.o \
 			nss_virt_if_stats.o \
 			nss_vlan.o \
diff --git a/Makefile.fsm b/Makefile.fsm
index 7f23771..566a7b7 100644
--- a/Makefile.fsm
+++ b/Makefile.fsm
@@ -93,6 +93,9 @@
 			nss_trustsec_tx_stats.o \
 			nss_tunipip6.o \
 			nss_tunipip6_log.o \
+			nss_unaligned.o \
+			nss_unaligned_log.o \
+			nss_unaligned_stats.o \
 			nss_virt_if.o \
 			nss_virt_if_stats.o \
 			nss_vlan.o \
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index d359323..eeecd49 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -72,6 +72,7 @@
 #include "nss_qrfs.h"
 #include "nss_c2c_tx.h"
 #include "nss_qvpn.h"
+#include "nss_unaligned.h"
 #endif
 
 /**
@@ -218,6 +219,8 @@
 		/**<Special interface number for QRFS. */
 #define NSS_GRE_REDIR_LAG_INTERFACE (NSS_SPECIAL_IF_START + 52)
 		/**< Special interface number for GRE redirect Link Aggregation interface. */
+#define NSS_UNALIGNED_INTERFACE (NSS_SPECIAL_IF_START + 54)
+		/**< Special interface number for unaligned handler. */
 #define NSS_QVPN_INTERFACE (NSS_SPECIAL_IF_START + 53)
 		/**< Special interface number for QVPN. */
 
diff --git a/exports/nss_unaligned.h b/exports/nss_unaligned.h
new file mode 100644
index 0000000..95f3443
--- /dev/null
+++ b/exports/nss_unaligned.h
@@ -0,0 +1,108 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/**
+ * @file nss_unaligned.h
+ *	NSS unaligned interface definitions.
+ */
+
+#ifndef __NSS_UNALIGNED_H
+#define __NSS_UNALIGNED_H
+
+/**
+ * @addtogroup nss_unaligned_subsystem
+ * @{
+ */
+
+#define NSS_UNALIGNED_EMULATED_OPS 64
+			/**< The number of operations that are emulated. */
+
+/**
+ * nss_unaligned_msg_types
+ *	Unaligned message types.
+ */
+enum nss_unaligned_msg_types {
+	NSS_UNALIGNED_MSG_STATS,	/**< Performance statistics message. */
+	NSS_UNALIGNED_MSG_MAX,		/**< Maximum unaligned message type. */
+};
+
+/**
+ * nss_unaligned_stats_op
+ *	Performance statistics for emulating a single operation.
+ */
+struct nss_unaligned_stats_op {
+	uint32_t opcode_primary;
+		/**< Primary operation code. */
+	uint32_t opcode_extension;
+		/**< Extension operation code, if applicable. */
+	uint64_t count;
+		/**< Number of times operation was emulated. */
+	uint32_t ticks_min;
+		/**< Minimum number of ticks spent emulating operation. */
+	uint32_t ticks_avg;
+		/**< Average number of ticks spent emulating operation. */
+	uint32_t ticks_max;
+		/**< Maximum number of ticks spent emulating operation. */
+	uint32_t padding;
+		/**< Used for consistent alignment, can be re-used. */
+};
+
+/**
+ * nss_unaligned_stats
+ *	Message containing all non-zero operation statistics.
+ */
+struct nss_unaligned_stats {
+	uint64_t trap_count;
+					/**< Number of unaligned traps encountered. */
+	struct nss_unaligned_stats_op ops[NSS_UNALIGNED_EMULATED_OPS];
+					/**< Statistics for each operation. */
+};
+
+/**
+ * nss_unaligned_msg
+ *	Message from unaligned handler node.
+ */
+struct nss_unaligned_msg {
+	struct nss_cmn_msg cm;		/**< Message header. */
+
+	/**
+	 * Unaligned message payload.
+	 */
+	union {
+		struct nss_unaligned_stats stats_msg;
+					/**< Message containing statistics. */
+	} msg;				/**< Message payload. */
+};
+
+/**
+ * nss_unaligned_register_handler()
+ *	Registers message handler on the NSS unaligned interface and
+ *	statistics dentry.
+ *
+ * @datatypes
+ * nss_ctx_instance
+ *
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ *
+ * @return
+ * None.
+ */
+void nss_unaligned_register_handler(struct nss_ctx_instance *nss_ctx);
+
+/**
+ * @}
+ */
+#endif
diff --git a/nss_core.h b/nss_core.h
index ead88d1..5a6d982 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -535,6 +535,8 @@
 	uint32_t irq_count;		/* Number of NSS core IRQs for statistics */
 	struct nss_worker_thread_stats *wt_stats;
 					/* Worker thread statistics */
+	struct nss_unaligned_stats unaligned_stats;
+					/* Unaligned emulation performance statistics */
 	struct nss_rx_cb_list nss_rx_interface_handlers[NSS_MAX_CORES][NSS_MAX_NET_INTERFACES];
 					/* NSS interface callback handlers */
 	struct nss_subsystem_dataplane_register subsys_dp_register[NSS_MAX_NET_INTERFACES];
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index 1d2cd95..1b48f0a 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -349,6 +349,7 @@
 	nss_qrfs_register_handler(nss_ctx);
 	nss_c2c_tx_register_handler(nss_ctx);
 	nss_c2c_rx_register_handler(nss_ctx);
+	nss_unaligned_register_handler(nss_ctx);
 
 	/*
 	 * Check functionalities are supported by this NSS core
diff --git a/nss_unaligned.c b/nss_unaligned.c
new file mode 100644
index 0000000..150a737
--- /dev/null
+++ b/nss_unaligned.c
@@ -0,0 +1,79 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/*
+ * nss_unaligned.c
+ *	NSS unaligned APIs
+ */
+
+#include "nss_tx_rx_common.h"
+#include "nss_unaligned_stats.h"
+#include "nss_unaligned_log.h"
+
+/*
+ * nss_unaligned_update_stats()
+ *	Updates the statistics in the nss_ctx.
+ */
+static void nss_unaligned_update_stats(struct nss_ctx_instance *nss_ctx,
+					struct nss_unaligned_stats *usm)
+{
+	spin_lock_bh(&nss_top_main.stats_lock);
+	nss_ctx->unaligned_stats = *usm;
+	spin_unlock_bh(&nss_top_main.stats_lock);
+}
+
+/*
+ * nss_unaligned_msg_handler()
+ *	Handles metadata messages on the unaligned interface.
+ */
+static void nss_unaligned_msg_handler(struct nss_ctx_instance *nss_ctx,
+		struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
+{
+	struct nss_unaligned_msg *um = (struct nss_unaligned_msg *)ncm;
+
+	/*
+	 * Sanity checks on message
+	 */
+	if (um->cm.type >= NSS_UNALIGNED_MSG_MAX) {
+		nss_warning("%p: message type out of range: %d\n", nss_ctx, um->cm.type);
+		return;
+	}
+
+	if (nss_cmn_get_msg_len(&(um->cm)) > sizeof(struct nss_unaligned_msg)) {
+		nss_warning("%p: message length is invalid: %d\n", nss_ctx, nss_cmn_get_msg_len(&(um->cm)));
+		return;
+	}
+
+	nss_unaligned_log_rx_msg(um);
+
+	switch (um->cm.type) {
+	case NSS_UNALIGNED_MSG_STATS:
+		nss_unaligned_update_stats(nss_ctx, &um->msg.stats_msg);
+		return;
+	}
+
+	nss_core_log_msg_failures(nss_ctx, ncm);
+}
+
+/*
+ * nss_unaligned_register_handler()
+ *	Registers message handler on the NSS unaligned interface and stats dentry.
+ */
+void nss_unaligned_register_handler(struct nss_ctx_instance *nss_ctx)
+{
+	nss_core_register_handler(nss_ctx, NSS_UNALIGNED_INTERFACE, nss_unaligned_msg_handler, NULL);
+	nss_unaligned_stats_dentry_create();
+}
diff --git a/nss_unaligned_log.c b/nss_unaligned_log.c
new file mode 100644
index 0000000..7a508e4
--- /dev/null
+++ b/nss_unaligned_log.c
@@ -0,0 +1,75 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/*
+ * nss_unaligned_log.c
+ *	NSS unaligned logger file.
+ */
+
+#include "nss_core.h"
+
+/*
+ * nss_unaligned_log_message_types_str
+ *	NSS unaligned message strings
+ */
+static int8_t *nss_unaligned_log_message_types_str[NSS_UNALIGNED_MSG_MAX] __maybe_unused = {
+	"Unaligned Stats Message",
+};
+
+/*
+ * nss_unaligned_log_verbose()
+ *	Log message contents.
+ */
+static void nss_unaligned_log_verbose(struct nss_unaligned_msg *um)
+{
+	switch (um->cm.type) {
+	case NSS_UNALIGNED_MSG_STATS:
+		/*
+		 * No log for valid stats message.
+		 */
+		break;
+
+	default:
+		nss_trace("%p: Invalid message type\n", um);
+		break;
+	}
+}
+
+/*
+ * nss_unaligned_log_rx_msg()
+ *	Log messages received from FW.
+ */
+void nss_unaligned_log_rx_msg(struct nss_unaligned_msg *um)
+{
+	if (um->cm.response >= NSS_CMN_RESPONSE_LAST) {
+		nss_warning("%p: Invalid response\n", um);
+		return;
+	}
+
+	if (um->cm.response == NSS_CMN_RESPONSE_NOTIFY || (um->cm.response == NSS_CMN_RESPONSE_ACK)) {
+		nss_info("%p: type[%d]:%s, response[%d]:%s\n", um, um->cm.type,
+			nss_unaligned_log_message_types_str[um->cm.type],
+			um->cm.response, nss_cmn_response_str[um->cm.response]);
+		goto verbose;
+	}
+
+	nss_info("%p: msg nack - type[%d]:%s, response[%d]:%s\n",
+		um, um->cm.type, nss_unaligned_log_message_types_str[um->cm.type],
+		um->cm.response, nss_cmn_response_str[um->cm.response]);
+
+verbose:
+	nss_unaligned_log_verbose(um);
+}
diff --git a/nss_unaligned_log.h b/nss_unaligned_log.h
new file mode 100644
index 0000000..98ec707
--- /dev/null
+++ b/nss_unaligned_log.h
@@ -0,0 +1,31 @@
+/*
+ ******************************************************************************
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_UNALIGNED_LOG_H__
+#define __NSS_UNALIGNED_LOG_H__
+
+/*
+ * nss_unaligned_log.h
+ *	NSS Unaligned Log Header File.
+ */
+
+/*
+ * nss_unaligned_log_rx_msg
+ *	Logs an unaligned trap handler message that is received from the NSS firmware.
+ */
+void nss_unaligned_log_rx_msg(struct nss_unaligned_msg *um);
+
+#endif /* __NSS_UNALIGNED_LOG_H__ */
diff --git a/nss_unaligned_stats.c b/nss_unaligned_stats.c
new file mode 100644
index 0000000..13591b2
--- /dev/null
+++ b/nss_unaligned_stats.c
@@ -0,0 +1,89 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#include "nss_tx_rx_common.h"
+#include "nss_stats.h"
+#include "nss_unaligned_stats.h"
+
+/*
+ * nss_unaligned_stats_read()
+ *	Read unaligned stats
+ */
+static ssize_t nss_unaligned_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	uint32_t max_output_lines = NSS_MAX_CORES * NSS_UNALIGNED_EMULATED_OPS;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	struct nss_unaligned_stats *stats_shadow;
+	uint32_t i, j;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(!lbuf)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_MAX_CORES * sizeof(struct nss_unaligned_stats), GFP_KERNEL);
+	if (unlikely(!stats_shadow)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; i < NSS_MAX_CORES; i++) {
+		stats_shadow[i] = nss_top_main.nss[i].unaligned_stats;
+	}
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; i < NSS_MAX_CORES; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+			"core: %u, total unaligned traps: %llu",
+			i, stats_shadow[i].trap_count);
+		for (j = 0; j < NSS_UNALIGNED_EMULATED_OPS; j++) {
+			struct nss_unaligned_stats_op op = stats_shadow[i].ops[j];
+			if (op.count == 0) {
+				break;
+			}
+
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"op: %2x, ext: %2x, count:%10llu, min: %10u, avg: %10u, max: %10u\n",
+				op.opcode_primary, op.opcode_extension, op.count, op.ticks_min,
+				op.ticks_avg, op.ticks_max);
+		}
+	}
+
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_unaligned_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(unaligned)
+
+/*
+ * nss_unaligned_stats_dentry_create()
+ *	Create unaligned statistics debug entry.
+ */
+void nss_unaligned_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("unaligned", &nss_unaligned_stats_ops);
+}
diff --git a/nss_unaligned_stats.h b/nss_unaligned_stats.h
new file mode 100644
index 0000000..761cda6
--- /dev/null
+++ b/nss_unaligned_stats.h
@@ -0,0 +1,22 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#ifndef __NSS_UNALIGNED_STATS_H
+#define __NSS_UNALIGNED_STATS_H
+
+extern void nss_unaligned_stats_dentry_create(void);
+
+#endif