[qca-nss-drv] Add support for eip197 crypto driver

This adds support for common crypto messaging which
can be used by different crypto HW supported by NSS

Change-Id: I6ca5600b530d1e569b8e4fbff7d1d7cc3300b37e
Signed-off-by: Sourav Poddar <souravp@codeaurora.org>
Signed-off-by: Samarjeet Banerjee <banerjee@codeaurora.org>
diff --git a/Makefile b/Makefile
index 460ca76..d961417 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,6 @@
 			nss_cmn.o \
 			nss_core.o \
 			nss_coredump.o \
-			nss_crypto.o \
 			nss_dtls.o \
 			nss_dynamic_interface.o \
 			nss_edma.o \
@@ -67,13 +66,15 @@
 
 ifeq ($(SoC),$(filter $(SoC),ipq806x ipq40xx))
 qca-nss-drv-objs += nss_data_plane/nss_data_plane_gmac.o \
-		    nss_hal/ipq806x/nss_hal_pvt.o
+		    nss_hal/ipq806x/nss_hal_pvt.o \
+		    nss_crypto.o
 ccflags-y += -I$(obj)/nss_hal/ipq806x -DNSS_HAL_IPQ806X_SUPPORT
 endif
 
 ifeq ($(SoC),$(filter $(SoC),ipq807x ipq807x_64))
 qca-nss-drv-objs += nss_data_plane/nss_data_plane_edma.o \
-		    nss_hal/ipq807x/nss_hal_pvt.o
+		    nss_hal/ipq807x/nss_hal_pvt.o \
+		    nss_crypto_cmn.o
 ccflags-y += -I$(obj)/nss_hal/ipq807x -DNSS_HAL_IPQ807x_SUPPORT
 endif
 
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 3bf70a4..e6cf1ae 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -43,6 +43,7 @@
 #include "nss_virt_if.h"
 #include "nss_pppoe.h"
 #include "nss_crypto.h"
+#include "nss_crypto_cmn.h"
 #include "nss_profiler.h"
 #include "nss_dynamic_interface.h"
 #include "nss_gre_redir.h"
@@ -128,11 +129,11 @@
 #define NSS_PROFILER_INTERFACE (NSS_SPECIAL_IF_START + 8)
 		/**< Special interface number for profile. */
 #define NSS_CRYPTO_INTERFACE (NSS_SPECIAL_IF_START + 9)
-		/**< Special interface number for crypto. */
+		/**< Special interface number for crypto CE5. */
 #define NSS_DTLS_INTERFACE (NSS_SPECIAL_IF_START + 10)
 		/**< Special interface number for DTLS. */
-#define NSS_RESERVED_INTERFACE2 (NSS_SPECIAL_IF_START + 11)
-		/**< Reserved interface 2. */
+#define NSS_CRYPTO_EIP197_INTERFACE (NSS_SPECIAL_IF_START + 11)
+		/**< Special interface number for crypto EIP197. */
 #define NSS_C2C_TX_INTERFACE (NSS_SPECIAL_IF_START + 12)
 		/**< Virtual interface number for IPSec tunnel. */
 #define NSS_IPSEC_RULE_INTERFACE (NSS_SPECIAL_IF_START + 18)
diff --git a/exports/nss_crypto_cmn.h b/exports/nss_crypto_cmn.h
new file mode 100644
index 0000000..1149a93
--- /dev/null
+++ b/exports/nss_crypto_cmn.h
@@ -0,0 +1,407 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, 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_crypto_cmn.h
+ *	NSS Crypto common interface definitions.
+ */
+#ifndef __NSS_CRYPTO_CMN_H
+#define __NSS_CRYPTO_CMN_H
+
+/**
+ * @addtogroup nss_crypto_cmn_subsystem
+ * @{
+ */
+
+/*
+ * nss_crypto_cmn_ctx message related array sizes
+ */
+#define NSS_CRYPTO_CMN_CTX_SPARE 4 /**< words */
+#define NSS_CRYPTO_CMN_VER_WORDS 4 /**< words */
+
+/**
+ * nss_crypto_cmn_algo
+ *	List of crypto algorithms supported
+ */
+enum nss_crypto_cmn_algo {
+	NSS_CRYPTO_CMN_ALGO_NULL,			/**< NULL tranform */
+	NSS_CRYPTO_CMN_ALGO_3DES_CBC,			/**< Async block cipher */
+	NSS_CRYPTO_CMN_ALGO_AES128_CBC,			/**< Async block cipher */
+	NSS_CRYPTO_CMN_ALGO_AES192_CBC,			/**< Async block cipher */
+	NSS_CRYPTO_CMN_ALGO_AES256_CBC,			/**< Async block cipher */
+	NSS_CRYPTO_CMN_ALGO_MD5_HMAC,			/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_SHA1_HMAC,			/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_SHA256_HMAC,		/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_AES128_GMAC,		/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_AES192_GMAC,		/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_AES256_GMAC,		/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_AES128_GCM_GMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CBC_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CBC_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CBC_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_GCM_GMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CBC_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CBC_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CBC_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_GCM_GMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CBC_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CBC_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CBC_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CTR_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CTR_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CTR_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CTR_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CTR_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CTR_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CTR_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CTR_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CTR_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_3DES_CBC_MD5_HMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_3DES_CBC_SHA1_HMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_3DES_CBC_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_MAX
+};
+
+/**
+ * nss_crypto_cmn_msg_type
+ *	Message types supported.
+ */
+enum nss_crypto_cmn_msg_type {
+	NSS_CRYPTO_CMN_MSG_TYPE_NONE = 0,		/**< Invalid message */
+	NSS_CRYPTO_CMN_MSG_TYPE_SETUP_NODE,		/**< Initialize Node */
+	NSS_CRYPTO_CMN_MSG_TYPE_SETUP_ENG,		/**< Initialize Engine */
+	NSS_CRYPTO_CMN_MSG_TYPE_SETUP_DMA,		/**< Initialize DMA pair */
+	NSS_CRYPTO_CMN_MSG_TYPE_SETUP_CTX,		/**< Update context info */
+	NSS_CRYPTO_CMN_MSG_TYPE_CLEAR_CTX,		/**< Clear context info */
+	NSS_CRYPTO_CMN_MSG_TYPE_VERIFY_CTX,		/**< Verify if context is active */
+	NSS_CRYPTO_CMN_MSG_TYPE_SYNC_NODE_STATS,	/**< Sync node stats */
+	NSS_CRYPTO_CMN_MSG_TYPE_SYNC_ENG_STATS,		/**< Sync engine stats */
+	NSS_CRYPTO_CMN_MSG_TYPE_SYNC_CTX_STATS,		/**< Sync context stats */
+	NSS_CRYPTO_CMN_MSG_TYPE_MAX
+};
+
+/**
+ * nss_crypto_cmn_msg_error
+ *	Message error types supported.
+ */
+enum nss_crypto_cmn_msg_error {
+	NSS_CRYPTO_CMN_MSG_ERROR_NONE = 0,
+	NSS_CRYPTO_CMN_MSG_ERROR_HDR_VERSION_NOSUPP,	/**< Common header version not supported */
+	NSS_CRYPTO_CMN_MSG_ERROR_NODE_CTX_RANGE,	/**< Context index out-of-range for node */
+	NSS_CRYPTO_CMN_MSG_ERROR_DMA_MASK,		/**< DMA mask is out-of-range */
+	NSS_CRYPTO_CMN_MSG_ERROR_DMA_POW2,		/**< DMA count is not a power-of-two */
+	NSS_CRYPTO_CMN_MSG_ERROR_DMA_MAX_TOKEN,		/**< DMA count exceeds token count */
+	NSS_CRYPTO_CMN_MSG_ERROR_DMA_TOKEN_ALLOC,	/**< Failed to allocate token */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_RANGE,		/**< Context index out-of-range */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_INUSE,		/**< Context has references */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_WORDS,		/**< Context size is bad */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_ALGO,		/**< Context algorithm is bad */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_ALLOC,		/**< Context alloc failed */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_NOUSE,		/**< Context has no references */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_FLAGS,		/**< Invalid context flags */
+	NSS_CRYPTO_CMN_MSG_ERROR_MAX
+};
+
+/**
+ * nss_crypto_cmn_ctx_flags
+ *	Context message specific flags.
+ */
+enum nss_crypto_cmn_ctx_flags {
+	NSS_CRYPTO_CMN_CTX_FLAGS_NONE = 0,		/**< Invalid flags. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SEC_OFFSET = 0x01,	/**< Secure offset is valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SPARE0 = 0x02,		/**< Spare word-0 valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SPARE1 = 0x04,		/**< Spare word-1 valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SPARE2 = 0x08,		/**< Spare word-2 valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SPARE3 = 0x10,		/**< Spare word-3 valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_MAX
+};
+
+/**
+ * nss_crypto_cmn_node
+ *	Node message for setting up the crypto node
+ *
+ * Note: Upon boot this is the first message sent by Host to NSS crypto
+ *	- It notifies the maximum number of Crypto Context.
+ *	- It notifies the maximum number of DMA rings.
+ *	- It returns the maximum size of crypto context record.
+ */
+struct nss_crypto_cmn_node {
+	uint32_t max_dma_rings;		/**< Maximum DMA rings supported */
+	uint32_t max_ctx;		/**< Maximum contexts */
+	uint32_t max_ctx_size;		/**< Maximum context size */
+};
+
+/**
+ * nss_crypto_cmn_engine
+ *	Engine message for setting up the instance of crypto engine
+ *
+ * Note: This is sent after 'node' message for each engine to
+ *	- Get valid DMA pairs supported by firmware
+ *	- Get maximum request/token count available in firmware
+ */
+struct nss_crypto_cmn_engine {
+	uint32_t fw_ver[NSS_CRYPTO_CMN_VER_WORDS];	/**< FW version */
+	uint32_t dma_mask;				/**< Max DMA rings */
+	uint32_t req_count;				/**< Token count */
+};
+
+/**
+ * nss_crypto_cmn_dma
+ *	DMA message for setting up each DMA pair per engine
+ */
+struct nss_crypto_cmn_dma {
+	struct {
+		uint32_t ring_addr;	/**< Ring physical address */
+		uint32_t write_reg;	/**< Write register address */
+		uint32_t read_reg;	/**< Read register address */
+	} in, out;
+
+	uint16_t count;			/**< No. of descriptors */
+	uint16_t pair_id;		/**< DMA pair-id */
+};
+
+/**
+ * nss_crypto_cmn_ctx
+ *	Context message for setting up a crypto context in firmware
+ */
+struct nss_crypto_cmn_ctx {
+	uint32_t words;					/**< Number of valid context words */
+	uint32_t addr;					/**< Address to config */
+	uint32_t spare[NSS_CRYPTO_CMN_CTX_SPARE];	/**< Context spare words */
+
+	uint16_t index;					/**< Crypto index */
+	uint16_t sec_offset;				/**< Secure offset for copying keys */
+
+	enum nss_crypto_cmn_algo algo;			/**< Crypto algorithm */
+	enum nss_crypto_cmn_ctx_flags flags;		/**< Context specific flags */
+};
+
+/**
+ * nss_crypto_cmn_stats
+ *	statistics message applicable for Node/Engine/Context
+ */
+struct nss_crypto_cmn_stats {
+	struct nss_cmn_node_stats nstats;	/**< Common node stats */
+	uint32_t fail_version;			/**< Version mismatch failures */
+	uint32_t fail_ctx;			/**< Context related failures */
+	uint32_t fail_dma;			/**< DMA descriptor full */
+};
+
+/**
+ * nss_crypto_cmn_msg
+ *	Crypto common configuration message.
+ */
+struct nss_crypto_cmn_msg {
+	struct nss_cmn_msg cm;				/**< Common header */
+	uint32_t seq_num;				/**< Seq no. for messages */
+	uint32_t uid;					/**< Unique ID to identify Engine/Context */
+
+	union {
+		struct nss_crypto_cmn_node node;	/**< Node message */
+		struct nss_crypto_cmn_engine eng;	/**< Engine message */
+		struct nss_crypto_cmn_dma dma;		/**< DMA message */
+		struct nss_crypto_cmn_ctx ctx;		/**< Context message */
+		struct nss_crypto_cmn_stats stats;	/**< Stats message */
+	} msg;
+};
+
+#ifdef __KERNEL__  /* only kernel will use */
+
+/**
+ * Callback function for receiving crypto transformation upon completion
+ *
+ * @datatype
+ * net_device \n
+ * sk_buff \n
+ * napi_struct
+ *
+ * @param[in] netdev  networking device registered for callback
+ * @param[in] skb     packet buffer
+ * @param[in] napi    NAPI pointer for Linux NAPI handling
+ *
+ * @return
+ * None.
+ */
+typedef void (*nss_crypto_cmn_buf_callback_t)(struct net_device *netdev, struct sk_buff *skb,
+						struct napi_struct *napi);
+
+/**
+ * Callback function for receiving crypto_cmn messages
+ *
+ * @datatype
+ * nss_crypto_cmn_msg
+ *
+ * @param[in] app_data  Context of the callback user
+ * @param[in] msg       Crypto common message
+ *
+ * @return
+ * None.
+ */
+typedef void (*nss_crypto_cmn_msg_callback_t)(void *app_data, struct nss_crypto_cmn_msg *msg);
+
+/**
+ * nss_crypto_cmn_tx_buf
+ *	Send crypto payload to firmware for transformation
+ *
+ * @datatype
+ * nss_ctx_instance \n
+ * sk_buff
+ *
+ * @param[in] nss_ctx  NSS context per NSS core
+ * @param[in] if_num   Crypto interface to send the buffer
+ * @param[in] skb      Crypto payload
+ *
+ * @return
+ * Status of the TX operation.
+ */
+extern nss_tx_status_t nss_crypto_cmn_tx_buf(struct nss_ctx_instance *nss_ctx, uint32_t if_num, struct sk_buff *skb);
+
+/**
+ * nss_crypto_cmn_tx_msg
+ *	Send crypto message to firmware for configuration
+ *
+ * @datatype
+ * nss_ctx_instance \n
+ * nss_crypto_cmn_msg
+ *
+ * @param[in] nss_ctx]  NSS context per NSS core
+ * @param[in] msg       Control message
+ *
+ * @return
+ * Status of the TX operation.
+ */
+extern nss_tx_status_t nss_crypto_cmn_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_crypto_cmn_msg *msg);
+
+/**
+ * nss_crypto_cmn_tx_msg
+ *	Send crypto message to firmware for configuration synchronously
+ *
+ * @datatype
+ * nss_ctx_instance \n
+ * nss_crypto_cmn_msg
+ *
+ * @param[in]     nss_ctx  NSS context per NSS core
+ * @param[in,out] msg      Crypto message, response data is copied
+ *
+ * @return
+ * Status of the TX operation.
+ *
+ * @note
+ * Response data for the  message is copied into the 'msg'.
+ * The caller should read the content of the 'msg' to find out errors.
+ * The caller needs to invoke this from a non-atomic context.
+ */
+extern nss_tx_status_t nss_crypto_cmn_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_crypto_cmn_msg *msg);
+
+/**
+ * nss_crypto_cmn_notify_register
+ *	register a event callback handler with NSS driver
+ *
+ * @datatype
+ * nss_crypto_cmn_msg_callback_t
+ *
+ * @param[in] cb            event callback function
+ * @param[in] app_data[IN]  context of the callback user
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_crypto_cmn_notify_register(nss_crypto_cmn_msg_callback_t cb, void *app_data);
+
+/**
+ * nss_crypto_cmn_notify_unregister
+ *	unregister the event callback handler with NSS driver
+ *
+ * @datatype
+ * nss_ctx_instance
+ *
+ * @param[in] nss_ctx  NSS context per NSS core
+ *
+ * @return
+ * None.
+ */
+extern void nss_crypto_cmn_notify_unregister(struct nss_ctx_instance *ctx);
+
+/**
+ * nss_crypto_cmn_data_register
+ *	crypto data register
+ *
+ * @datatype
+ * nss_crypto_cmn_buf_callback_t \n
+ * net_device
+ *
+ * @param[in] if_num    interface number
+ * @param[in] cb        callback function
+ * @param[in] netdev    net device
+ * @param[in] features  features supported
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_crypto_cmn_data_register(uint32_t if_num,
+						nss_crypto_cmn_buf_callback_t cb,
+						struct net_device *netdev,
+						uint32_t features);
+
+/**
+ * nss_crypto_cmn_data_unregister
+ *	crypto data unregister
+ *
+ * @param[in] ctx     NSS context per NSS core
+ * @param[in] if_num  interface number
+ *
+ * @return
+ * None.
+ */
+extern void nss_crypto_cmn_data_unregister(struct nss_ctx_instance *ctx, uint32_t if_num);
+
+/**
+ * nss_crypto_cmn_get_context
+ *	get the per NSS core context enabled for crypto
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_crypto_cmn_get_context(void);
+
+/**
+ * nss_crypto_cmn_msg_init
+ *	crypto common message init
+ *
+ * @datatype
+ * nss_crypto_cmn_msg \n
+ * nss_crypto_cmn_msg_callback_t
+ *
+ * @param[in] ncm       crypto cmn message
+ * @param[in] if_num    interface number
+ * @param[in] type      type
+ * @param[in] len       common message length
+ * @param[in] cb        callback function
+ * @param[in] app_data  appllication data
+ *
+ * @return
+ * None.
+ */
+extern void nss_crypto_cmn_msg_init(struct nss_crypto_cmn_msg *ncm, uint16_t if_num,
+				uint32_t type, uint32_t len, nss_crypto_cmn_msg_callback_t cb,
+				void *app_data);
+
+#endif /*__KERNEL__ */
+
+/**
+ * @}
+ */
+#endif
diff --git a/nss_core.h b/nss_core.h
index 485782f..0a8c6e9 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -1025,6 +1025,7 @@
 	nss_ipsec_msg_callback_t ipsec_decap_callback;
 					/* IPsec event callback function */
 	nss_crypto_msg_callback_t crypto_msg_callback;
+	nss_crypto_cmn_msg_callback_t crypto_cmn_msg_callback;
 	nss_crypto_buf_callback_t crypto_buf_callback;
 	nss_crypto_pm_event_callback_t crypto_pm_callback;
 					/* crypto interface callback functions */
@@ -1360,7 +1361,7 @@
  * APIs provided by nss_tx_rx.c
  */
 extern void nss_rx_handle_status_pkt(struct nss_ctx_instance *nss_ctx, struct sk_buff *nbuf);
-extern void nss_crypto_buf_handler(struct nss_ctx_instance *nss_ctx, void *buf, uint32_t paddr, uint16_t len);
+
 /*
  * APIs provided by nss_stats.c
  */
diff --git a/nss_crypto_cmn.c b/nss_crypto_cmn.c
new file mode 100644
index 0000000..b62b3cc
--- /dev/null
+++ b/nss_crypto_cmn.c
@@ -0,0 +1,400 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2013,2015-2017, 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_crypto_cmn.c
+ *	NSS Crypto common API implementation
+ */
+
+#include "nss_tx_rx_common.h"
+#include "nss_crypto_cmn.h"
+
+/*
+ * Amount time the synchronous message should wait for response from
+ * NSS before the timeout happens. After the timeout the message
+ * response even if it arrives has to be discarded. Typically, the
+ * time needs to be selected based on the worst case time in case of
+ * peak throughput between host & NSS.
+ */
+#define NSS_CRYPTO_CMN_TX_TIMEO_TICKS msecs_to_jiffies(3000) /* milliseconds */
+
+/*
+ * Private data structure to hold state for
+ * the crypto specific NSS interaction
+ */
+struct nss_crypto_cmn_pvt {
+	struct semaphore sem;		/* used for synchronizing 'tx_msg_sync' */
+	struct completion complete;	/* completion callback */
+	atomic_t seq_no;		/* used for tracking tx_msg_sync requests */
+};
+
+/*
+ * This is a single instance applicable for all crypto synchronous
+ * messaging interaction with NSS.
+ */
+static struct nss_crypto_cmn_pvt g_nss_crypto_cmn;
+
+/*
+ * nss_crypto_cmn_msg_handler()
+ *	this handles all the IPsec events and responses
+ */
+static void nss_crypto_cmn_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm,
+					void *app_data __attribute((unused)))
+{
+	struct nss_crypto_cmn_msg *nim = (struct nss_crypto_cmn_msg *)ncm;
+	nss_crypto_cmn_msg_callback_t cb = NULL;
+
+	/*
+	 * Sanity check the message type
+	 */
+	if (ncm->type > NSS_CRYPTO_CMN_MSG_TYPE_MAX) {
+		nss_warning("%p: rx message type out of range: %d", nss_ctx, ncm->type);
+		return;
+	}
+
+	/*
+	 * Check if the message structure length matches that of Host side. In case
+	 * of failure this indicates ether the structure is different or this is not
+	 * the intended interface.
+	 */
+	if (nss_cmn_get_msg_len(ncm) != sizeof(*nim)) {
+		nss_warning("%p: rx message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
+		return;
+	}
+
+	if (ncm->response == NSS_CMN_RESPONSE_LAST) {
+		nss_warning("%p: rx message response for if %d, type %d, is invalid: %d", nss_ctx,
+				ncm->interface, ncm->type, ncm->response);
+		return;
+	}
+
+	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->crypto_cmn_msg_callback;
+		ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->crypto_ctx;
+	}
+
+	nss_core_log_msg_failures(nss_ctx, ncm);
+
+	/*
+	 * Load, Test & call
+	 */
+	cb = (nss_crypto_cmn_msg_callback_t)ncm->cb;
+	if (unlikely(!cb)) {
+		nss_warning("%p: rx handler has been unregistered for i/f: %d", nss_ctx, ncm->interface);
+		return;
+	}
+
+	cb((void *)ncm->app_data, nim);
+}
+
+/*
+ * nss_crypto_cmn_tx_msg
+ *	Send crypto config to NSS.
+ */
+nss_tx_status_t nss_crypto_cmn_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_crypto_cmn_msg *msg)
+{
+	struct nss_top_instance *nss_top = &nss_top_main;
+	struct nss_cmn_msg *ncm = &msg->cm;
+	uint16_t msg_len = nss_cmn_get_msg_len(ncm);
+
+	struct sk_buff *nbuf;
+	int32_t status;
+
+	nss_info("%p: tx message %d for if %d", nss_ctx, ncm->type, ncm->interface);
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: message dropped, core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
+
+	BUILD_BUG_ON(NSS_NBUF_PAYLOAD_SIZE < sizeof(*msg));
+
+	if (ncm->type > NSS_CRYPTO_CMN_MSG_TYPE_MAX) {
+		nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * Check if the message structure length matches the structure length. Otherwise
+	 * the sender accidentally programmed a incorrect length into the message.
+	 */
+	if (msg_len != sizeof(*msg)) {
+		nss_warning("%p: message request len bad: %d", nss_ctx, msg_len);
+		return NSS_TX_FAILURE_BAD_PARAM;
+	}
+
+	nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+	if (unlikely(!nbuf)) {
+		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
+		nss_warning("%p: tx config dropped as command allocation failed", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	nss_trace("%p: msg params version:%d, interface:%d, type:%d, cb:%p, app_data:%p, len:%d",
+			nss_ctx, ncm->version, ncm->interface, ncm->type,
+			(void *)ncm->cb, (void *)ncm->app_data, ncm->len);
+
+	memcpy(skb_put(nbuf, msg_len), msg, msg_len);
+
+	status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
+	switch (status) {
+	case NSS_CORE_STATUS_SUCCESS:
+		break;
+
+	case NSS_CORE_STATUS_FAILURE_QUEUE: 	/* queue full condition */
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: H2N queue full for tx_msg", nss_ctx);
+		return NSS_TX_FAILURE_QUEUE;
+
+	default:				/* all other tx failures */
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: general failure for tx_msg", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
+	return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_tx_msg);
+
+/*
+ * nss_crypto_cmn_tx_msg_cb()
+ *	Callback to handle the synchronous completion of messages.
+ */
+static void nss_crypto_cmn_tx_msg_cb(void *app_data, struct nss_crypto_cmn_msg *nim)
+{
+	struct nss_crypto_cmn_pvt *pvt = &g_nss_crypto_cmn;
+	struct nss_crypto_cmn_msg *resp = (struct nss_crypto_cmn_msg *)nim->cm.app_data;
+
+	/*
+	 * Only update the message structure if the sequence no. matches
+	 * Otherwise, a timeout might have happened in between and we
+	 * are probably receiving the completion for an older message
+	 */
+	if (atomic_read(&pvt->seq_no) == nim->seq_num) {
+		memcpy(resp, nim, sizeof(struct nss_crypto_cmn_msg));
+		complete(&pvt->complete);
+	}
+}
+
+/*
+ * nss_crypto_cmn_tx_msg_sync()
+ *	Transmit a crypto message to NSS firmware synchronously.
+ */
+nss_tx_status_t nss_crypto_cmn_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_crypto_cmn_msg *msg)
+{
+	struct nss_crypto_cmn_pvt *pvt = &g_nss_crypto_cmn;
+	nss_tx_status_t status;
+	int ret = 0;
+
+	down(&pvt->sem);
+	atomic_inc(&pvt->seq_no);
+
+	/*
+	 * this is a synchronous message; overload the callback
+	 * and app_data
+	 */
+	msg->cm.cb = (nss_ptr_t)nss_crypto_cmn_tx_msg_cb;
+	msg->cm.app_data = (nss_ptr_t)msg;
+	msg->seq_num = atomic_read(&pvt->seq_no);
+
+	status = nss_crypto_cmn_tx_msg(nss_ctx, msg);
+	if (status != NSS_TX_SUCCESS) {
+		nss_warning("%p: tx_msg failed", nss_ctx);
+		up(&pvt->sem);
+		return status;
+	}
+
+	/*
+	 * Note: This cannot be called in atomic context
+	 */
+	ret = wait_for_completion_timeout(&pvt->complete, NSS_CRYPTO_CMN_TX_TIMEO_TICKS);
+	if (!ret) {
+		atomic_inc(&pvt->seq_no);
+		nss_warning("%p: tx_msg_sync timed out", nss_ctx);
+		up(&pvt->sem);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * This ensures that the even if the response arrives on a different
+	 * CPU core the data copied by the response callback will be visible
+	 * to the caller which is sleeping for it on a different core. For
+	 * further details read Linux/Documentation/memory-barrier.txt
+	 */
+	smp_rmb();
+	up(&pvt->sem);
+
+	return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_tx_msg_sync);
+
+/*
+ * nss_crypto_cmn_tx_buf()
+ *	NSS crypto TX data API. Sends a crypto buffer to NSS.
+ */
+nss_tx_status_t nss_crypto_cmn_tx_buf(struct nss_ctx_instance *nss_ctx, uint32_t if_num,
+					struct sk_buff *skb)
+{
+	int32_t status;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: tx_data packet dropped as core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
+
+	status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_DATA_QUEUE_0, H2N_BUFFER_PACKET, 0);
+	switch (status) {
+	case NSS_CORE_STATUS_SUCCESS:
+		break;
+
+	case NSS_CORE_STATUS_FAILURE_QUEUE: /* queue full condition */
+		nss_warning("%p: H2N queue full for tx_buf", nss_ctx);
+		return NSS_TX_FAILURE_QUEUE;
+
+	default:
+		nss_warning("%p: general failure for tx_buf", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * Kick the NSS awake so it can process our new entry.
+	 */
+	nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
+	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CRYPTO_REQ]);
+
+	return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_tx_buf);
+
+/*
+ * nss_crypto_cmn_notify_register()
+ *	register message notifier for crypto interface
+ */
+struct nss_ctx_instance *nss_crypto_cmn_notify_register(nss_crypto_cmn_msg_callback_t cb, void *app_data)
+{
+	struct nss_top_instance *nss_top = &nss_top_main;
+	struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_top->crypto_handler_id];
+
+	nss_top->crypto_ctx = app_data;
+	nss_top->crypto_cmn_msg_callback = cb;
+
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_notify_register);
+
+/*
+ * nss_crypto_cmn_notify_unregister()
+ *	De-register the message notifier for crypto interface
+ */
+void nss_crypto_cmn_notify_unregister(struct nss_ctx_instance *nss_ctx)
+{
+	struct nss_top_instance *nss_top = &nss_top_main;
+
+	nss_top->crypto_ctx = NULL;
+	nss_top->crypto_cmn_msg_callback = NULL;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_notify_unregister);
+
+/*
+ * nss_crypto_cmn_data_register()
+ *	Register the data callback routine
+ */
+struct nss_ctx_instance *nss_crypto_cmn_data_register(uint32_t if_num, nss_crypto_cmn_buf_callback_t cb,
+		struct net_device *netdev, uint32_t features)
+{
+	struct nss_ctx_instance *nss_ctx;
+
+	if (if_num < NSS_SPECIAL_IF_START) {
+		nss_warning("%p: interface number is not special interface %d", nss_ctx, if_num);
+		return NULL;
+	}
+
+	nss_ctx = &nss_top_main.nss[nss_top_main.crypto_handler_id];
+
+	/*
+	 * avoid multiple registration for same interface number
+	 */
+	if (nss_ctx->subsys_dp_register[if_num].cb)
+		return nss_ctx;
+
+	/*
+	 * Note: no locking is required for updating this as
+	 * the registration is only a module load time operation.
+	 */
+	nss_ctx->subsys_dp_register[if_num].cb = cb;
+	nss_ctx->subsys_dp_register[if_num].app_data = NULL;
+	nss_ctx->subsys_dp_register[if_num].ndev = netdev;
+	nss_ctx->subsys_dp_register[if_num].features = features;
+
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_data_register);
+
+/*
+ * nss_crypto_cmn_data_unregister()
+ *	De-register the data callback routine
+ */
+void nss_crypto_cmn_data_unregister(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
+{
+	if (if_num < NSS_SPECIAL_IF_START) {
+		nss_warning("%p: interface number is not special interface %d", nss_ctx, if_num);
+		return;
+	}
+
+	/*
+	 * Note: no locking is required for updating this as
+	 * the registration is only a module load time operation.
+	 */
+	nss_ctx->subsys_dp_register[if_num].cb = NULL;
+	nss_ctx->subsys_dp_register[if_num].app_data = NULL;
+	nss_ctx->subsys_dp_register[if_num].ndev = NULL;
+	nss_ctx->subsys_dp_register[if_num].features = 0;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_data_unregister);
+
+/*
+ * nss_crypto_cmn_get_context()
+ *	get NSS context instance for crypto handle
+ */
+struct nss_ctx_instance *nss_crypto_cmn_get_context(void)
+{
+	return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.crypto_handler_id];
+}
+EXPORT_SYMBOL(nss_crypto_cmn_get_context);
+
+/*
+ * nss_crypto_cmn_register_handler()
+ */
+void nss_crypto_cmn_register_handler(void)
+{
+	sema_init(&g_nss_crypto_cmn.sem, 1);
+	init_completion(&g_nss_crypto_cmn.complete);
+	nss_core_register_handler(NSS_CRYPTO_EIP197_INTERFACE, nss_crypto_cmn_msg_handler, NULL);
+}
+
+/*
+ * nss_crypto_cmn_msg_init()
+ *	Initialize crypto message
+ */
+void nss_crypto_cmn_msg_init(struct nss_crypto_cmn_msg *ncm, uint16_t if_num, uint32_t type,
+			uint32_t len, nss_crypto_cmn_msg_callback_t cb, void *app_data)
+{
+	nss_cmn_msg_init(&ncm->cm, if_num, type, len, (void *)cb, app_data);
+}
+EXPORT_SYMBOL(nss_crypto_cmn_msg_init);
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index 7970602..ce1d021 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -386,10 +386,18 @@
 		nss_ipv6_reasm_register_handler();
 	}
 
+	/*
+	 * TODO: when Crypto is moved to Core-1 it needs to
+	 * flush based on nss_top->crypto_enabled
+	 */
 	if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
-		nss_top->crypto_enabled = 1;
 		nss_top->crypto_handler_id = nss_dev->id;
+#if defined(NSS_HAL_IPQ807x_SUPPORT)
+		nss_crypto_cmn_register_handler();
+#else
+		nss_top->crypto_enabled = 1;
 		nss_crypto_register_handler();
+#endif
 	}
 
 	if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index ef7894a..5882507 100644
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -178,6 +178,7 @@
  */
 void nss_phys_if_register_handler(uint32_t if_num);
 extern void nss_crypto_register_handler(void);
+extern void nss_crypto_cmn_register_handler(void);
 extern void nss_ipsec_register_handler(void);
 extern void nss_ipv4_register_handler(void);
 extern void nss_ipv4_reasm_register_handler(void);