[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);