Forráskód Böngészése

qcacmn: Introduce hashing framework support for crypto

This change incorporates support for the hashing framework,
enabling key storage for individual links in the n-link MLO.
The implementation includes the addition of new APIs
specifically designed to accommodate the crypto hashing
framework.

Change-Id: I9305c4a71b8970a8a6037d6d80f11c6139a77bd8
CRs-Fixed: 3498849
Aasir Rasheed 2 éve
szülő
commit
b39b050462

+ 88 - 0
umac/cmn_services/crypto/src/wlan_crypto_def_i.h

@@ -31,6 +31,8 @@
 
 /* Number of bits per byte */
 #define CRYPTO_NBBY  8
+/* Default link id for legacy connection */
+#define CRYPTO_MAX_LINK_IDX 0xFF
 
 /* Macros for handling unaligned memory accesses */
 
@@ -562,4 +564,90 @@ static inline int wlan_get_tid(const void *data)
 	} else
 		return WLAN_NONQOS_SEQ;
 }
+
+union crypto_align_mac_addr {
+	uint8_t raw[QDF_MAC_ADDR_SIZE];
+	struct {
+		uint16_t bytes_ab;
+		uint16_t bytes_cd;
+		uint16_t bytes_ef;
+	} align2;
+	struct {
+		uint32_t bytes_abcd;
+		uint16_t bytes_ef;
+	} align4;
+	struct __packed {
+		uint16_t bytes_ab;
+		uint32_t bytes_cdef;
+	} align4_2;
+};
+
+/**
+ * struct wlan_crypto_key_entry - crypto key entry structure
+ * @mac_addr: mac addr
+ * @is_active: active key entry
+ * @link_id: link id
+ * @vdev_id: vdev id
+ * @keys: crypto keys
+ * @hash_list_elem: hash list element
+ */
+struct wlan_crypto_key_entry {
+	union crypto_align_mac_addr mac_addr;
+	bool is_active;
+	uint8_t link_id;
+	uint8_t vdev_id;
+	struct wlan_crypto_keys keys;
+
+	TAILQ_ENTRY(wlan_crypto_key_entry) hash_list_elem;
+};
+
+struct crypto_psoc_priv_obj {
+	/** @crypto_key_lock: lock for crypto key table */
+	qdf_mutex_t crypto_key_lock;
+	/** @crypto_key_lock: lock for crypto key table */
+	qdf_atomic_t crypto_key_cnt;
+	struct {
+		/** @mask: mask bits */
+		uint32_t mask;
+		/** @idx_bits: index to shift bits */
+		uint32_t idx_bits;
+		/** @bins: crypto key table */
+		TAILQ_HEAD(, wlan_crypto_key_entry) * bins;
+	} crypto_key_holder;
+};
+
+/**
+ * struct pdev_crypto - pdev object structure for crypto
+ * @pdev_obj: pdev object
+ */
+struct pdev_crypto {
+	struct wlan_objmgr_pdev *pdev_obj;
+};
+
+/**
+ * crypto_add_entry - add key entry to hashing framework
+ * @psoc: psoc handler
+ * @link_id: link id
+ * @mac_addr: mac addr
+ * @crypto_key: crypto key
+ * @key_index: key index
+ * Return: zero on success
+ */
+QDF_STATUS crypto_add_entry(struct crypto_psoc_priv_obj *psoc,
+			    uint8_t link_id,
+			    uint8_t *mac_addr,
+			    struct wlan_crypto_key *crypto_key,
+			    uint8_t key_index);
+/**
+ * crypto_hash_find_by_linkid_and_macaddr - find crypto entry by link id
+ * @psoc: psoc handler
+ * @link_id: link id
+ * @mac_addr: mac addr
+ * Return: crypto key entry on success
+ */
+struct
+wlan_crypto_key_entry * crypto_hash_find_by_linkid_and_macaddr(
+				struct crypto_psoc_priv_obj *psoc,
+				uint8_t link_id,
+				uint8_t *mac_addr);
 #endif /* end of _WLAN_CRYPTO_DEF_I_H_ */

+ 588 - 3
umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c

@@ -39,10 +39,418 @@
 #include "wlan_crypto_fils_api.h"
 #endif
 
+#define CRYPTO_MAX_HASH_IDX 16
+#define CRYPTO_MAX_HASH_ENTRY 1024
+qdf_mutex_t crypto_lock;
 
 extern const struct wlan_crypto_cipher
 				*wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_MAX];
 
+static inline int crypto_log2_ceil(unsigned int value)
+{
+	unsigned int tmp = value;
+	int log2 = -1;
+
+	crypto_info("crypto log value %d ", value);
+	while (tmp) {
+		log2++;
+		tmp >>= 1;
+	}
+	if (1 << log2 != value)
+		log2++;
+	return log2;
+}
+
+#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+static QDF_STATUS wlan_crypto_hash_init(struct crypto_psoc_priv_obj *psoc)
+{
+	int log2, hash_elems, i;
+
+	log2 = crypto_log2_ceil(CRYPTO_MAX_HASH_IDX);
+	hash_elems = 1 << log2;
+
+	psoc->crypto_key_holder.mask = hash_elems - 1;
+	psoc->crypto_key_holder.idx_bits = log2;
+
+	/* allocate an array of TAILQ mec object lists */
+	psoc->crypto_key_holder.bins = qdf_mem_malloc(
+					hash_elems *
+					sizeof(TAILQ_HEAD(anonymous_tail_q,
+							  crypto_hash_entry)));
+
+	if (!psoc->crypto_key_holder.bins)
+		return QDF_STATUS_E_NOMEM;
+
+	for (i = 0; i < hash_elems; i++)
+		TAILQ_INIT(&psoc->crypto_key_holder.bins[i]);
+
+	qdf_mutex_create(&psoc->crypto_key_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+static inline uint32_t crypto_hash_index(struct crypto_psoc_priv_obj *psoc,
+					 union crypto_align_mac_addr *mac_addr,
+					 uint8_t link_id)
+{
+	uint32_t index;
+
+	index =
+		mac_addr->align2.bytes_ab ^
+		mac_addr->align2.bytes_cd ^
+		mac_addr->align2.bytes_ef;
+	index ^= link_id;
+	index ^= index >> psoc->crypto_key_holder.idx_bits;
+	index &= psoc->crypto_key_holder.mask;
+	return index;
+}
+
+static inline int crypto_is_mac_addr_same(
+	union crypto_align_mac_addr *mac_addr1,
+	union crypto_align_mac_addr *mac_addr2)
+{
+	/*
+	 * Intentionally use & rather than &&.
+	 * because the operands are binary rather than generic boolean,
+	 * the functionality is equivalent.
+	 * Using && has the advantage of short-circuited evaluation,
+	 * but using & has the advantage of no conditional branching,
+	 * which is a more significant benefit.
+	 */
+	return ((mac_addr1->align4.bytes_abcd == mac_addr2->align4.bytes_abcd)
+		& (mac_addr1->align4.bytes_ef == mac_addr2->align4.bytes_ef));
+}
+
+struct
+wlan_crypto_key_entry *crypto_hash_find_by_linkid_and_macaddr(
+			struct crypto_psoc_priv_obj *psoc,
+			uint8_t link_id,
+			uint8_t *mac_addr)
+{
+	union crypto_align_mac_addr local_mac_addr_aligned, *local_mac_addr;
+	uint32_t index;
+	struct wlan_crypto_key_entry *hash_entry;
+
+	qdf_mem_copy(&local_mac_addr_aligned.raw[0],
+		     mac_addr, QDF_MAC_ADDR_SIZE);
+	local_mac_addr = &local_mac_addr_aligned;
+
+	index = crypto_hash_index(psoc, local_mac_addr, link_id);
+	TAILQ_FOREACH(hash_entry, &psoc->crypto_key_holder.bins[index],
+		      hash_list_elem) {
+		if (link_id == hash_entry->link_id &&
+		    crypto_is_mac_addr_same(
+					      local_mac_addr,
+					      &hash_entry->mac_addr)) {
+			crypto_debug("crypto found entry link id %d mac addr"
+				     QDF_MAC_ADDR_FMT,
+				     hash_entry->link_id,
+				     QDF_MAC_ADDR_REF(mac_addr));
+			return hash_entry;
+		}
+	}
+	return NULL;
+}
+
+static inline void crypto_hash_add(struct crypto_psoc_priv_obj *psoc,
+				   struct wlan_crypto_key_entry *hash_entry,
+				   uint8_t link_id)
+{
+	uint32_t index;
+
+	index = crypto_hash_index(psoc, &hash_entry->mac_addr, link_id);
+	crypto_debug("crypto hash add index %d ", index);
+	qdf_mutex_acquire(&psoc->crypto_key_lock);
+	TAILQ_INSERT_TAIL(&psoc->crypto_key_holder.bins[index], hash_entry,
+			  hash_list_elem);
+	qdf_mutex_release(&psoc->crypto_key_lock);
+}
+
+static int is_igtk(uint16_t keyix)
+{
+	if (keyix < WLAN_CRYPTO_MAXKEYIDX)
+		return 0;
+	else if (keyix - WLAN_CRYPTO_MAXKEYIDX >= WLAN_CRYPTO_MAXIGTKKEYIDX)
+		return 0;
+	else
+		return 1;
+}
+
+QDF_STATUS crypto_add_entry(struct crypto_psoc_priv_obj *psoc,
+			    uint8_t link_id,
+			    uint8_t *mac_addr,
+			    struct wlan_crypto_key *crypto_key,
+			    uint8_t key_index)
+{
+	struct wlan_crypto_key_entry *crypto_entry = NULL;
+
+	crypto_debug("crypto add entry link id %d mac_addr: " QDF_MAC_ADDR_FMT,
+		     link_id, QDF_MAC_ADDR_REF(mac_addr));
+
+	if (qdf_unlikely(qdf_atomic_read(&psoc->crypto_key_cnt) >=
+					 CRYPTO_MAX_HASH_ENTRY)) {
+		crypto_err("max crypto hash entry limit reached mac_addr: "
+			   QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(mac_addr));
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	qdf_mutex_acquire(&psoc->crypto_key_lock);
+	crypto_entry = crypto_hash_find_by_linkid_and_macaddr(psoc, link_id,
+							      mac_addr);
+	qdf_mutex_release(&psoc->crypto_key_lock);
+
+	if (qdf_likely(!crypto_entry)) {
+		crypto_entry = (struct wlan_crypto_key_entry *)
+			qdf_mem_malloc(sizeof(struct wlan_crypto_key_entry));
+
+		if (qdf_unlikely(!crypto_entry))
+			return QDF_STATUS_E_NOMEM;
+
+		qdf_copy_macaddr((struct qdf_mac_addr *)&crypto_entry->mac_addr.raw[0],
+				 (struct qdf_mac_addr *)mac_addr);
+		crypto_entry->link_id = link_id;
+		crypto_hash_add(psoc, crypto_entry, link_id);
+		qdf_atomic_inc(&psoc->crypto_key_cnt);
+		crypto_entry->is_active = 1;
+	}
+
+	if (key_index < WLAN_CRYPTO_MAXKEYIDX) {
+		crypto_entry->keys.key[key_index] = crypto_key;
+	} else if (is_igtk(key_index)) {
+		crypto_entry->keys.igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX] =
+		crypto_key;
+		crypto_entry->keys.def_igtk_tx_keyid =
+				key_index - WLAN_CRYPTO_MAXKEYIDX;
+		crypto_entry->keys.igtk_key_type = crypto_key->cipher_type;
+	} else {
+		crypto_entry->keys.bigtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX
+				- WLAN_CRYPTO_MAXIGTKKEYIDX] = crypto_key;
+		crypto_entry->keys.def_bigtk_tx_keyid =
+				key_index - WLAN_CRYPTO_MAXKEYIDX
+				- WLAN_CRYPTO_MAXIGTKKEYIDX;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+static void crypto_remove_entry(struct crypto_psoc_priv_obj *psoc,
+				struct wlan_crypto_key_entry *crypto_entry,
+				void *ptr)
+{
+	int i = 0;
+
+	uint32_t index = crypto_hash_index(psoc, &crypto_entry->mac_addr,
+					   crypto_entry->link_id);
+	TAILQ_HEAD(, wlan_crypto_key_entry) * free_list = ptr;
+
+	crypto_debug("crypto remove entry key index %d link id %d crypto_entry %pK ",
+		     index, crypto_entry->link_id,
+		     crypto_entry);
+
+	for (i = 0; i < WLAN_CRYPTO_MAX_VLANKEYIX; i++) {
+		if (crypto_entry->keys.key[i]) {
+			qdf_mem_free(crypto_entry->keys.key[i]);
+			crypto_entry->keys.key[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < WLAN_CRYPTO_MAXIGTKKEYIDX; i++) {
+		if (crypto_entry->keys.igtk_key[i]) {
+			qdf_mem_free(crypto_entry->keys.igtk_key[i]);
+			crypto_entry->keys.igtk_key[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < WLAN_CRYPTO_MAXBIGTKKEYIDX; i++) {
+		if (crypto_entry->keys.bigtk_key[i]) {
+			qdf_mem_free(crypto_entry->keys.bigtk_key[i]);
+			crypto_entry->keys.bigtk_key[i] = NULL;
+		}
+	}
+	/* Reset All key index as well */
+	crypto_entry->keys.def_tx_keyid = 0;
+	crypto_entry->keys.def_igtk_tx_keyid = 0;
+	crypto_entry->keys.def_bigtk_tx_keyid = 0;
+
+	TAILQ_REMOVE(&psoc->crypto_key_holder.bins[index], crypto_entry,
+		     hash_list_elem);
+	TAILQ_INSERT_TAIL(free_list, crypto_entry, hash_list_elem);
+}
+
+static void crypto_free_list(struct crypto_psoc_priv_obj *psoc, void *ptr)
+{
+	struct wlan_crypto_key_entry *crypto_entry, *hash_entry_next;
+
+	TAILQ_HEAD(, wlan_crypto_key_entry) * free_list = ptr;
+
+	TAILQ_FOREACH_SAFE(crypto_entry, free_list, hash_list_elem,
+			   hash_entry_next) {
+		crypto_debug("crypto delete for link_id %d mac_addr "
+			     QDF_MAC_ADDR_FMT, crypto_entry->link_id,
+			     QDF_MAC_ADDR_REF(&crypto_entry->mac_addr));
+		qdf_mem_free(crypto_entry);
+		if (!qdf_atomic_read(&psoc->crypto_key_cnt))
+			crypto_debug("Invalid crypto_key_cnt %d",
+				     psoc->crypto_key_cnt);
+		else
+			qdf_atomic_dec(&psoc->crypto_key_cnt);
+	}
+}
+
+static void crypto_flush_entries(struct crypto_psoc_priv_obj *psoc)
+{
+	unsigned int index;
+	struct wlan_crypto_key_entry *hash_entry, *hash_entry_next;
+
+	TAILQ_HEAD(, wlan_crypto_key_entry) free_list;
+	TAILQ_INIT(&free_list);
+
+	if (!psoc->crypto_key_holder.mask)
+		return;
+
+	if (!psoc->crypto_key_holder.bins)
+		return;
+
+	if (!qdf_atomic_read(&psoc->crypto_key_cnt))
+		return;
+
+	qdf_mutex_acquire(&psoc->crypto_key_lock);
+	for (index = 0; index <= psoc->crypto_key_holder.mask; index++) {
+		if (!TAILQ_EMPTY(&psoc->crypto_key_holder.bins[index])) {
+			TAILQ_FOREACH_SAFE(
+				hash_entry,
+				&psoc->crypto_key_holder.bins[index],
+				hash_list_elem, hash_entry_next) {
+				crypto_remove_entry(psoc, hash_entry,
+						    &free_list);
+			}
+		}
+	}
+	crypto_free_list(psoc, &free_list);
+	qdf_mutex_release(&psoc->crypto_key_lock);
+}
+
+static void crypto_hash_deinit(struct crypto_psoc_priv_obj *psoc)
+{
+	crypto_flush_entries(psoc);
+	qdf_mem_free(psoc->crypto_key_holder.bins);
+	psoc->crypto_key_holder.bins = NULL;
+	qdf_mutex_destroy(&psoc->crypto_key_lock);
+}
+
+static QDF_STATUS wlan_crypto_psoc_obj_create_handler(
+				struct wlan_objmgr_psoc *psoc,
+				void *arg)
+{
+	QDF_STATUS status;
+	struct crypto_psoc_priv_obj *crypto_psoc_obj;
+
+	crypto_psoc_obj = qdf_mem_malloc(sizeof(*crypto_psoc_obj));
+	if (!crypto_psoc_obj)
+		return QDF_STATUS_E_NOMEM;
+
+	status = wlan_objmgr_psoc_component_obj_attach(psoc,
+						       WLAN_UMAC_COMP_CRYPTO,
+						       (void *)crypto_psoc_obj,
+						       QDF_STATUS_SUCCESS);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		qdf_mem_free(crypto_psoc_obj);
+		crypto_err("failed to attach crypto psoc priv object");
+		return status;
+	}
+	return status;
+}
+
+static QDF_STATUS wlan_crypto_psoc_obj_destroy_handler(
+				struct wlan_objmgr_psoc *psoc,
+				void *arg)
+{
+	QDF_STATUS status;
+	struct crypto_psoc_priv_obj *crypto_psoc_obj;
+
+	crypto_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
+						psoc,
+						WLAN_UMAC_COMP_CRYPTO);
+	if (!crypto_psoc_obj) {
+		crypto_err("failed to get crypto obj in psoc");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	status = wlan_objmgr_psoc_component_obj_detach(psoc,
+						       WLAN_UMAC_COMP_CRYPTO,
+						       crypto_psoc_obj);
+	if (QDF_IS_STATUS_ERROR(status))
+		crypto_err("failed to detach crypto psoc priv object");
+
+	qdf_mem_free(crypto_psoc_obj);
+	return status;
+}
+
+static QDF_STATUS
+wlan_crypto_pdev_obj_create_handler(
+struct wlan_objmgr_pdev *pdev, void *arg)
+{
+	struct pdev_crypto *pdev_priv = NULL;
+	struct crypto_psoc_priv_obj *crypto_psoc_obj;
+	struct wlan_objmgr_psoc *psoc;
+
+	if (!pdev) {
+		crypto_err("crypto pdev is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	pdev_priv = (struct pdev_crypto *)
+		 qdf_mem_malloc(sizeof(struct pdev_crypto));
+	if (!pdev_priv) {
+		crypto_err("failed to allocate crypto pdev object");
+		return QDF_STATUS_E_NOMEM;
+	}
+	psoc = wlan_pdev_get_psoc(pdev);
+	crypto_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
+					psoc,
+					WLAN_UMAC_COMP_CRYPTO);
+	wlan_crypto_hash_init(crypto_psoc_obj);
+
+	pdev_priv->pdev_obj = pdev;
+	wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_UMAC_COMP_CRYPTO,
+					      (void *)pdev_priv,
+					      QDF_STATUS_SUCCESS);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static QDF_STATUS
+wlan_crypto_pdev_obj_destroy_handler(
+struct wlan_objmgr_pdev *pdev, void *arg)
+{
+	struct pdev_crypto *pdev_priv = NULL;
+	struct crypto_psoc_priv_obj *crypto_psoc_obj;
+	struct wlan_objmgr_psoc *psoc;
+
+	if (!pdev) {
+		crypto_err("crypto pdev is NULL\n");
+		return QDF_STATUS_E_FAILURE;
+	}
+	psoc = wlan_pdev_get_psoc(pdev);
+	crypto_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj(
+					psoc,
+					WLAN_UMAC_COMP_CRYPTO);
+
+	crypto_hash_deinit(crypto_psoc_obj);
+	pdev_priv =
+	wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CRYPTO);
+	if (pdev_priv) {
+		wlan_objmgr_pdev_component_obj_detach(
+		pdev, WLAN_UMAC_COMP_CRYPTO, (void *)pdev_priv);
+		qdf_mem_free(pdev_priv);
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 static QDF_STATUS wlan_crypto_register_all_ciphers(
 					struct wlan_crypto_params *crypto_param)
 {
@@ -213,7 +621,6 @@ void wlan_crypto_free_vdev_key(struct wlan_objmgr_vdev *vdev)
 {
 	struct wlan_crypto_comp_priv *crypto_priv;
 
-	crypto_debug("free key for vdev %d", wlan_vdev_get_id(vdev));
 	crypto_priv = wlan_get_vdev_crypto_obj(vdev);
 	if (!crypto_priv) {
 		crypto_err("crypto_priv NULL");
@@ -280,15 +687,155 @@ static QDF_STATUS wlan_crypto_peer_obj_destroy_handler(
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+static int register_psoc_create_handler(void)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = wlan_objmgr_register_psoc_create_handler(
+			WLAN_UMAC_COMP_CRYPTO,
+			wlan_crypto_psoc_obj_create_handler,
+			NULL);
+	return status;
+}
+
+static int register_psoc_destroy_handler(void)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = wlan_objmgr_register_psoc_destroy_handler(
+			WLAN_UMAC_COMP_CRYPTO,
+			wlan_crypto_psoc_obj_destroy_handler,
+			NULL);
+	return status;
+}
+
+static int unregister_psoc_create_handler(void)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = wlan_objmgr_unregister_psoc_create_handler(
+			WLAN_UMAC_COMP_CRYPTO,
+			wlan_crypto_psoc_obj_create_handler,
+			NULL);
+	return status;
+}
+
+static int unregister_psoc_destroy_handler(void)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = wlan_objmgr_unregister_psoc_destroy_handler(
+			WLAN_UMAC_COMP_CRYPTO,
+			wlan_crypto_psoc_obj_destroy_handler,
+			NULL);
+	return status;
+}
+
+static int register_pdev_create_handler(void)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = wlan_objmgr_register_pdev_create_handler(
+			WLAN_UMAC_COMP_CRYPTO,
+			wlan_crypto_pdev_obj_create_handler, NULL);
+	return status;
+}
+
+static int register_pdev_destroy_handler(void)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = wlan_objmgr_register_pdev_destroy_handler(
+			WLAN_UMAC_COMP_CRYPTO,
+			wlan_crypto_pdev_obj_destroy_handler, NULL);
+	return status;
+}
+
+static int unregister_pdev_create_handler(void)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = wlan_objmgr_unregister_pdev_create_handler(
+			WLAN_UMAC_COMP_CRYPTO,
+			wlan_crypto_pdev_obj_create_handler,
+			NULL);
+	return status;
+}
+
+static int unregister_pdev_destroy_handler(void)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	status = wlan_objmgr_unregister_pdev_destroy_handler(
+			WLAN_UMAC_COMP_CRYPTO,
+			wlan_crypto_pdev_obj_destroy_handler,
+			NULL);
+	return status;
+}
+#else
+static int register_psoc_create_handler(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static int register_psoc_destroy_handler(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static int unregister_psoc_create_handler(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static int unregister_psoc_destroy_handler(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static int register_pdev_create_handler(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static int register_pdev_destroy_handler(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static int unregister_pdev_create_handler(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static int unregister_pdev_destroy_handler(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 QDF_STATUS __wlan_crypto_init(void)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
+	status = register_psoc_create_handler();
+	if (QDF_IS_STATUS_ERROR(status)) {
+		crypto_err("psoc creation failure");
+		return status;
+	}
+
+	status = register_pdev_create_handler();
+	if (QDF_IS_STATUS_ERROR(status)) {
+		crypto_err("pdev creation failure");
+		goto err_pdev_create;
+	}
+
 	status = wlan_objmgr_register_vdev_create_handler(
 				WLAN_UMAC_COMP_CRYPTO,
 				wlan_crypto_vdev_obj_create_handler, NULL);
 	if (status != QDF_STATUS_SUCCESS)
-		return status;
+		goto err_vdev_create;
 
 	status = wlan_objmgr_register_peer_create_handler(
 				WLAN_UMAC_COMP_CRYPTO,
@@ -296,6 +843,18 @@ QDF_STATUS __wlan_crypto_init(void)
 	if (status != QDF_STATUS_SUCCESS)
 		goto err_peer_create;
 
+	status = register_psoc_destroy_handler();
+	if (QDF_IS_STATUS_ERROR(status)) {
+		crypto_err("psoc destroy failure");
+		goto err_psoc_delete;
+	}
+
+	status = register_pdev_destroy_handler();
+	if (QDF_IS_STATUS_ERROR(status)) {
+		crypto_err("pdev destroy failure");
+		goto err_pdev_destroy;
+	}
+
 	status = wlan_objmgr_register_vdev_destroy_handler(
 				WLAN_UMAC_COMP_CRYPTO,
 				wlan_crypto_vdev_obj_destroy_handler, NULL);
@@ -313,12 +872,19 @@ err_peer_delete:
 	wlan_objmgr_unregister_vdev_destroy_handler(WLAN_UMAC_COMP_CRYPTO,
 			wlan_crypto_vdev_obj_destroy_handler, NULL);
 err_vdev_delete:
+	unregister_pdev_destroy_handler();
+err_pdev_destroy:
+	unregister_psoc_destroy_handler();
+err_psoc_delete:
 	wlan_objmgr_unregister_peer_create_handler(WLAN_UMAC_COMP_CRYPTO,
 			wlan_crypto_peer_obj_create_handler, NULL);
 err_peer_create:
 	wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_CRYPTO,
 			wlan_crypto_vdev_obj_create_handler, NULL);
-
+err_vdev_create:
+	unregister_pdev_create_handler();
+err_pdev_create:
+	unregister_psoc_create_handler();
 register_success:
 	return status;
 }
@@ -326,6 +892,16 @@ register_success:
 QDF_STATUS __wlan_crypto_deinit(void)
 {
 
+	if (unregister_psoc_create_handler()
+			!= QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (unregister_pdev_create_handler()
+			!= QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	if (wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_CRYPTO,
 			wlan_crypto_vdev_obj_create_handler, NULL)
 			!= QDF_STATUS_SUCCESS) {
@@ -350,5 +926,14 @@ QDF_STATUS __wlan_crypto_deinit(void)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (unregister_pdev_destroy_handler()
+			!= QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (unregister_psoc_destroy_handler()
+			!= QDF_STATUS_SUCCESS) {
+		return QDF_STATUS_E_FAILURE;
+	}
 	return QDF_STATUS_SUCCESS;
 }