qcacmn: Add Netlink deinit functionality in Spectral

Define os_if_spectral_netlink_deinit to close the Spectral socket and
de-register the os_if callbacks

Change-Id: I3d054c2a2d630d4d959861d3620592010d04c09a
CRs-Fixed: 2186113
diff --git a/os_if/linux/spectral/inc/os_if_spectral_netlink.h b/os_if/linux/spectral/inc/os_if_spectral_netlink.h
index 3d71502..0f7379d 100644
--- a/os_if/linux/spectral/inc/os_if_spectral_netlink.h
+++ b/os_if/linux/spectral/inc/os_if_spectral_netlink.h
@@ -33,8 +33,8 @@
 void os_if_spectral_nl_data_ready(struct sk_buff *skb);
 #endif /* VERSION CHECK */
 
-#ifndef NETLINK_ATHEROS
-#define NETLINK_ATHEROS              (NETLINK_GENERIC + 1)
+#ifndef SPECTRAL_NETLINK
+#define SPECTRAL_NETLINK              (NETLINK_GENERIC + 1)
 #endif
 #define MAX_SPECTRAL_PAYLOAD         1500
 
@@ -46,9 +46,8 @@
  * and register the NL handlers with Spectral target_if
  * @pdev: Pointer to pdev
  *
- * Sending Netlink messages to application layer and de-initialization of
- * netlink related data structures are defined in os_if layer,
- * they need to be registered with Spectral target_if
+ * Preparing socket buffer and sending Netlink messages to application layer are
+ * defined in os_if layer, they need to be registered with Spectral target_if
  *
  * Return: None
  */
@@ -64,4 +63,12 @@
  */
 void *os_if_spectral_prep_skb(struct wlan_objmgr_pdev *pdev);
 
+/**
+ * os_if_spectral_netlink_deinit() - De-initialize Spectral Netlink data
+ * structures and de-register the NL handlers from Spectral target_if
+ * @pdev: Pointer to pdev
+ *
+ * Return: None
+ */
+void os_if_spectral_netlink_deinit(struct wlan_objmgr_pdev *pdev);
 #endif /* _OS_IF_SPECTRAL_NETLINK_H */
diff --git a/os_if/linux/spectral/src/os_if_spectral_netlink.c b/os_if/linux/spectral/src/os_if_spectral_netlink.c
index 9ca122f..8a6c389 100644
--- a/os_if/linux/spectral/src/os_if_spectral_netlink.c
+++ b/os_if/linux/spectral/src/os_if_spectral_netlink.c
@@ -26,8 +26,8 @@
 #include <net/cnss_nl.h>
 #endif
 
-struct sock *os_if_spectral_nl_sock;
 #ifndef CNSS_GENL
+static struct sock *os_if_spectral_nl_sock;
 static atomic_t spectral_nl_users = ATOMIC_INIT(0);
 #endif
 
@@ -84,7 +84,7 @@
 {
 	os_if_spectral_nl_sock =
 	    (struct sock *)netlink_kernel_create(&init_net,
-						 NETLINK_ATHEROS, cfg);
+						 SPECTRAL_NETLINK, cfg);
 }
 #elif KERNEL_VERSION(3, 6, 0) <= LINUX_VERSION_CODE
 static void
@@ -92,7 +92,7 @@
 {
 	os_if_spectral_nl_sock =
 	    (struct sock *)netlink_kernel_create(&init_net,
-						 NETLINK_ATHEROS,
+						 SPECTRAL_NETLINK,
 						 THIS_MODULE, cfg);
 }
 #elif (KERNEL_VERSION(2, 6, 31) > LINUX_VERSION_CODE)
@@ -101,7 +101,7 @@
 {
 	os_if_spectral_nl_sock =
 	    (struct sock *)netlink_kernel_create(
-		NETLINK_ATHEROS, 1,
+		SPECTRAL_NETLINK, 1,
 		&os_if_spectral_nl_data_ready,
 		THIS_MODULE);
 }
@@ -115,7 +115,7 @@
 	cfg->input = &os_if_spectral_nl_data_ready;
 	os_if_spectral_nl_sock =
 	    (struct sock *)netlink_kernel_create(&init_net,
-						 NETLINK_ATHEROS, cfg);
+						 SPECTRAL_NETLINK, cfg);
 }
 #else
 static void
@@ -124,7 +124,7 @@
 	os_if_spectral_nl_sock =
 	    (struct sock *)netlink_kernel_create(
 		&init_net,
-		NETLINK_ATHEROS, 1,
+		SPECTRAL_NETLINK, 1,
 		&os_if_spectral_nl_data_ready,
 		NULL, THIS_MODULE);
 }
@@ -239,7 +239,7 @@
 		spectral_err("PDEV SPECTRAL object is NULL!");
 		return NULL;
 	}
-	ps->skb = dev_alloc_skb(MAX_SPECTRAL_PAYLOAD);
+	ps->skb = qdf_nbuf_alloc(NULL, MAX_SPECTRAL_PAYLOAD, 0, 0, false);
 
 	if (!ps->skb) {
 		spectral_err("allocate skb (len=%u) failed",
@@ -247,19 +247,17 @@
 		return NULL;
 	}
 
-	skb_put(ps->skb, MAX_SPECTRAL_PAYLOAD);
+	qdf_nbuf_put_tail(ps->skb, MAX_SPECTRAL_PAYLOAD);
 	spectral_nlh = (struct nlmsghdr *)ps->skb->data;
 
-	OS_MEMZERO(spectral_nlh,
-		   sizeof(*spectral_nlh));
+	OS_MEMZERO(spectral_nlh, sizeof(*spectral_nlh));
 
 	/*
 	 * Possible bug that size of  struct spectral_samp_msg and
 	 * SPECTRAL_MSG differ by 3 bytes  so we miss 3 bytes
 	 */
 
-	spectral_nlh->nlmsg_len =
-	    NLMSG_SPACE(sizeof(struct spectral_samp_msg));
+	spectral_nlh->nlmsg_len = NLMSG_SPACE(sizeof(struct spectral_samp_msg));
 	spectral_nlh->nlmsg_pid = 0;
 	spectral_nlh->nlmsg_flags = 0;
 	spectral_nlh->nlmsg_type = WLAN_NL_MSG_SPECTRAL_SCAN;
@@ -460,9 +458,31 @@
 	nl_cb.get_nbuff = os_if_spectral_prep_skb;
 	nl_cb.send_nl_bcast = os_if_spectral_nl_bcast_msg;
 	nl_cb.send_nl_unicast = os_if_spectral_nl_unicast_msg;
-	nl_cb.destroy_netlink = os_if_spectral_destroy_netlink;
 
 	if (sptrl_ctx->sptrlc_register_netlink_cb)
 		sptrl_ctx->sptrlc_register_netlink_cb(pdev, &nl_cb);
 }
 EXPORT_SYMBOL(os_if_spectral_netlink_init);
+
+void os_if_spectral_netlink_deinit(struct wlan_objmgr_pdev *pdev)
+{
+	struct spectral_context *sptrl_ctx;
+
+	if (!pdev) {
+		spectral_err("PDEV is NULL!");
+		return;
+	}
+
+	sptrl_ctx = spectral_get_spectral_ctx_from_pdev(pdev);
+
+	if (!sptrl_ctx) {
+		spectral_err("Spectral context is NULL!");
+		return;
+	}
+
+	if (sptrl_ctx->sptrlc_deregister_netlink_cb)
+		sptrl_ctx->sptrlc_deregister_netlink_cb(pdev);
+
+	os_if_spectral_destroy_netlink(pdev);
+}
+EXPORT_SYMBOL(os_if_spectral_netlink_deinit);
diff --git a/spectral/core/spectral_defs_i.h b/spectral/core/spectral_defs_i.h
index 510f502..2e0be87 100644
--- a/spectral/core/spectral_defs_i.h
+++ b/spectral/core/spectral_defs_i.h
@@ -92,6 +92,7 @@
  * @sptrlc_register_wmi_spectral_cmd_ops: Register wmi_spectral_cmd operations
  * @sptrlc_register_netlink_cb: Register Netlink callbacks
  * @sptrlc_use_nl_bcast: Check whether to use Netlink broadcast/unicast
+ * @sptrlc_deregister_netlink_cb: De-register Netlink callbacks
  */
 struct spectral_context {
 	struct wlan_objmgr_psoc *psoc_obj;
@@ -128,6 +129,7 @@
 		struct wlan_objmgr_pdev *pdev,
 		struct spectral_nl_cb *nl_cb);
 	bool (*sptrlc_use_nl_bcast)(struct wlan_objmgr_pdev *pdev);
+	void (*sptrlc_deregister_netlink_cb)(struct wlan_objmgr_pdev *pdev);
 };
 
 #endif				/* _SPECTRAL_DEFS_I_H_ */
diff --git a/spectral/core/spectral_direct_attach.c b/spectral/core/spectral_direct_attach.c
index c532503..13fcc53 100644
--- a/spectral/core/spectral_direct_attach.c
+++ b/spectral/core/spectral_direct_attach.c
@@ -44,4 +44,5 @@
 	    tgt_register_wmi_spectral_cmd_ops;
 	sc->sptrlc_register_netlink_cb = tgt_spectral_register_nl_cb;
 	sc->sptrlc_use_nl_bcast = tgt_spectral_use_nl_bcast;
+	sc->sptrlc_deregister_netlink_cb = tgt_spectral_deregister_nl_cb;
 }
diff --git a/spectral/core/spectral_offload.c b/spectral/core/spectral_offload.c
index dd09c78..e6bccee 100644
--- a/spectral/core/spectral_offload.c
+++ b/spectral/core/spectral_offload.c
@@ -45,4 +45,5 @@
 	    tgt_register_wmi_spectral_cmd_ops;
 	sc->sptrlc_register_netlink_cb = tgt_spectral_register_nl_cb;
 	sc->sptrlc_use_nl_bcast = tgt_spectral_use_nl_bcast;
+	sc->sptrlc_deregister_netlink_cb = tgt_spectral_deregister_nl_cb;
 }
diff --git a/spectral/dispatcher/inc/wlan_spectral_public_structs.h b/spectral/dispatcher/inc/wlan_spectral_public_structs.h
index f65611a..1ca5125 100644
--- a/spectral/dispatcher/inc/wlan_spectral_public_structs.h
+++ b/spectral/dispatcher/inc/wlan_spectral_public_structs.h
@@ -510,13 +510,11 @@
  * @get_nbuff:      Get the socket buffer to send the data to the application
  * @send_nl_bcast:  Send data to the application using netlink broadcast
  * @send_nl_unicast:  Send data to the application using netlink unicast
- * @destroy_netlink:    De-initialize Netlink data structures
  */
 struct spectral_nl_cb {
 	void *(*get_nbuff)(struct wlan_objmgr_pdev *pdev);
 	int (*send_nl_bcast)(struct wlan_objmgr_pdev *pdev);
 	int (*send_nl_unicast)(struct wlan_objmgr_pdev *pdev);
-	int (*destroy_netlink)(struct wlan_objmgr_pdev *pdev);
 };
 #ifdef WIN32
 #pragma pack(pop, spectral)
diff --git a/spectral/dispatcher/inc/wlan_spectral_tgt_api.h b/spectral/dispatcher/inc/wlan_spectral_tgt_api.h
index f3f574f..c26802d 100644
--- a/spectral/dispatcher/inc/wlan_spectral_tgt_api.h
+++ b/spectral/dispatcher/inc/wlan_spectral_tgt_api.h
@@ -211,4 +211,12 @@
  * Return: true for broadcast, false for unicast
  */
 bool tgt_spectral_use_nl_bcast(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * tgt_spectral_deregister_nl_cb() - De-register Netlink callbacks
+ * @pdev: Pointer to pdev object
+ *
+ * Return: void
+ */
+void tgt_spectral_deregister_nl_cb(struct wlan_objmgr_pdev *pdev);
 #endif /* _WLAN_SPECTRAL_TGT_API_H_ */
diff --git a/spectral/dispatcher/src/wlan_spectral_tgt_api.c b/spectral/dispatcher/src/wlan_spectral_tgt_api.c
index 63b666b..e64ef3f 100644
--- a/spectral/dispatcher/src/wlan_spectral_tgt_api.c
+++ b/spectral/dispatcher/src/wlan_spectral_tgt_api.c
@@ -205,6 +205,10 @@
 	struct wlan_objmgr_psoc *psoc = NULL;
 	struct wlan_lmac_if_sptrl_tx_ops *psptrl_tx_ops = NULL;
 
+	if (!pdev) {
+		spectral_err("PDEV is NULL!");
+		return;
+	}
 	psoc = wlan_pdev_get_psoc(pdev);
 
 	psptrl_tx_ops = &psoc->soc_cb.tx_ops.sptrl_tx_ops;
@@ -225,3 +229,19 @@
 
 	return psptrl_tx_ops->sptrlto_use_nl_bcast(pdev);
 }
+
+void tgt_spectral_deregister_nl_cb(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+	struct wlan_lmac_if_sptrl_tx_ops *psptrl_tx_ops = NULL;
+
+	if (!pdev) {
+		spectral_err("PDEV is NULL!");
+		return;
+	}
+	psoc = wlan_pdev_get_psoc(pdev);
+
+	psptrl_tx_ops = &psoc->soc_cb.tx_ops.sptrl_tx_ops;
+
+	psptrl_tx_ops->sptrlto_deregister_netlink_cb(pdev);
+}
diff --git a/target_if/spectral/target_if_spectral.c b/target_if/spectral/target_if_spectral.c
index 97fc385..35119a0 100644
--- a/target_if/spectral/target_if_spectral.c
+++ b/target_if/spectral/target_if_spectral.c
@@ -1841,8 +1841,6 @@
 
 		target_if_spectral_detach_simulation(spectral);
 
-		spectral->nl_cb.destroy_netlink(spectral->pdev_obj);
-
 		qdf_spinlock_destroy(&spectral->spectral_lock);
 		qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock);
 
@@ -2785,6 +2783,26 @@
 	return spectral->use_nl_bcast;
 }
 
+/**
+ * target_if_deregister_netlink_cb() - De-register Netlink callbacks
+ * @pdev: Pointer to pdev object
+ *
+ * Return: void
+ */
+static void
+target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev)
+{
+	struct target_if_spectral *spectral = NULL;
+
+	spectral = get_target_if_spectral_handle_from_pdev(pdev);
+	if (!spectral) {
+		spectral_err("SPECTRAL : Module doesn't exist");
+		return;
+	}
+
+	qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb));
+}
+
 void
 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
 {
@@ -2818,6 +2836,8 @@
 	    target_if_register_netlink_cb;
 	tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast =
 	    target_if_use_nl_bcast;
+	tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb =
+	    target_if_deregister_netlink_cb;
 }
 EXPORT_SYMBOL(target_if_sptrl_register_tx_ops);
 
diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
index 4bfa618..8423df0 100644
--- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
+++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
@@ -336,6 +336,7 @@
  * @sptrlto_get_spectral_diagstats: Get Spectral diagnostic statistics
  * @sptrlto_register_netlink_cb: Register Spectral Netlink callbacks
  * @sptrlto_use_nl_bcast: Get whether to use Netlink broadcast/unicast
+ * @sptrlto_deregister_netlink_cb: De-register Spectral Netlink callbacks
  **/
 struct wlan_lmac_if_sptrl_tx_ops {
 	void *(*sptrlto_pdev_spectral_init)(struct wlan_objmgr_pdev *pdev);
@@ -364,6 +365,7 @@
 		struct wlan_objmgr_pdev *pdev,
 		struct spectral_nl_cb *nl_cb);
 	bool (*sptrlto_use_nl_bcast)(struct wlan_objmgr_pdev *pdev);
+	void (*sptrlto_deregister_netlink_cb)(struct wlan_objmgr_pdev *pdev);
 };
 #endif /* WLAN_CONV_SPECTRAL_ENABLE */