wlan: ptt_socket_app enhance

Make ptt_socket_app as a WLAN NL Daemon application.
Then user do not need manually run ptt_socket_app for FTM and DIAG.

Change-Id: I08e39e93f8616b8f9107fd9fb50ee91a33f92bf3
CRs-fixed: 509738
diff --git a/CORE/HDD/src/wlan_hdd_early_suspend.c b/CORE/HDD/src/wlan_hdd_early_suspend.c
index c5f26c6..34751b3 100644
--- a/CORE/HDD/src/wlan_hdd_early_suspend.c
+++ b/CORE/HDD/src/wlan_hdd_early_suspend.c
@@ -1705,7 +1705,11 @@
        unregister_netdevice_notifier(&hdd_netdev_notifier);
        /* Clean up HDD Nlink Service */
        send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
+#ifdef WLAN_KD_READY_NOTIFIER
+       nl_srv_exit(pHddCtx->ptt_pid);
+#else
        nl_srv_exit();
+#endif /* WLAN_KD_READY_NOTIFIER */
        /* Free up dynamically allocated members inside HDD Adapter */
        kfree(pHddCtx->cfg_ini);
        pHddCtx->cfg_ini= NULL;
diff --git a/CORE/HDD/src/wlan_hdd_ftm.c b/CORE/HDD/src/wlan_hdd_ftm.c
index 5ba3e52..56d29fe 100644
--- a/CORE/HDD/src/wlan_hdd_ftm.c
+++ b/CORE/HDD/src/wlan_hdd_ftm.c
@@ -1108,8 +1108,11 @@
     return VOS_STATUS_SUCCESS;
 
 err_nl_srv_init:
+#ifdef WLAN_KD_READY_NOTIFIER
+nl_srv_exit(pHddCtx->ptt_pid);
+#else
 nl_srv_exit();
-
+#endif /* WLAN_KD_READY_NOTIFIER */
 err_ftm_register_wext_close:
 hdd_UnregisterWext(pAdapter->dev);
 
@@ -1154,8 +1157,11 @@
 
     vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
 
+#ifdef WLAN_KD_READY_NOTIFIER
+    nl_srv_exit(pHddCtx->ptt_pid);
+#else
     nl_srv_exit();
-
+#endif /* WLAN_KD_READY_NOTIFIER */
     //TODO----------
     //Deregister the device with the kernel
     hdd_UnregisterWext(pAdapter->dev);
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index ed27ee9..605b712 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -5037,6 +5037,7 @@
 
    vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
 
+
    //This requires pMac access, Call this before vos_close().
    hdd_unregister_mcast_bcast_filter(pHddCtx);
 
@@ -5068,7 +5069,11 @@
 
    //Clean up HDD Nlink Service
    send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
+#ifdef WLAN_KD_READY_NOTIFIER
+   nl_srv_exit(pHddCtx->ptt_pid);
+#else
    nl_srv_exit();
+#endif /* WLAN_KD_READY_NOTIFIER */
 
    /* Cancel the vote for XO Core ON. 
     * This is done here to ensure there is no race condition since MC, TX and WD threads have
@@ -5949,8 +5954,11 @@
    goto success;
 
 err_nl_srv:
+#ifdef WLAN_KD_READY_NOTIFIER
+   nl_srv_exit(pHddCtx->ptt_pid);
+#else
    nl_srv_exit();
-
+#endif /* WLAN_KD_READY_NOTIFIER */
 err_reg_netdev:
    unregister_netdevice_notifier(&hdd_netdev_notifier);
 
diff --git a/CORE/SVC/inc/wlan_nlink_srv.h b/CORE/SVC/inc/wlan_nlink_srv.h
index 65632d9..82a699b 100644
--- a/CORE/SVC/inc/wlan_nlink_srv.h
+++ b/CORE/SVC/inc/wlan_nlink_srv.h
@@ -63,10 +63,17 @@
 typedef int (* nl_srv_msg_callback)(struct sk_buff * skb);
 
 int nl_srv_init(void);
+#ifdef WLAN_KD_READY_NOTIFIER
+void nl_srv_exit(int dst_pid);
+#else
 void nl_srv_exit(void);
+#endif /* WLAN_KD_READY_NOTIFIER */
 int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler);
 int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler);
 int nl_srv_ucast(struct sk_buff * skb, int dst_pid);
 int nl_srv_bcast(struct sk_buff * skb);
-
+#ifdef WLAN_KD_READY_NOTIFIER
+void nl_srv_nl_ready_indication(void);
+void nl_srv_nl_close_indication(int pid);
+#endif /* WLAN_KD_READY_NOTIFIER */
 #endif
diff --git a/CORE/SVC/src/nlink/wlan_nlink_srv.c b/CORE/SVC/src/nlink/wlan_nlink_srv.c
index e74a9da..efcaefd 100644
--- a/CORE/SVC/src/nlink/wlan_nlink_srv.c
+++ b/CORE/SVC/src/nlink/wlan_nlink_srv.c
@@ -62,6 +62,11 @@
 static struct sock *nl_srv_sock;
 static nl_srv_msg_callback nl_srv_msg_handler[NLINK_MAX_CALLBACKS];
 
+#ifdef WLAN_KD_READY_NOTIFIER
+const char driverLoaded[]   = "KNLREADY";
+const char driverUnLoaded[] = "KNLCLOSE";
+#endif /* WLAN_KD_READY_NOTIFIER */
+
 //Forward declaration
 static void nl_srv_rcv (struct sk_buff *sk);
 static void nl_srv_rcv_skb (struct sk_buff *skb);
@@ -106,8 +111,18 @@
  * Deinit the netlink service.
  * Netlink service is unusable after this.
  */
+#ifdef WLAN_KD_READY_NOTIFIER
+void nl_srv_exit(int dst_pid)
+#else
 void nl_srv_exit(void)
+#endif /* WLAN_KD_READY_NOTIFIER */
 {
+#ifdef WLAN_KD_READY_NOTIFIER
+   if (0 != dst_pid)
+   {
+      nl_srv_nl_close_indication(dst_pid);
+   }
+#endif /* WLAN_KD_READY_NOTIFIER */
    netlink_kernel_release(nl_srv_sock);
 }
 
@@ -294,3 +309,92 @@
    }
 }
 
+#ifdef WLAN_KD_READY_NOTIFIER
+/*
+ * Send Net Link interface ready indication to application daemon
+ * Each netlink message will have a message of type tAniMsgHdr inside.
+ */
+void nl_srv_nl_ready_indication
+(
+   void
+)
+{
+   struct sk_buff *skb = NULL;
+   struct nlmsghdr *nlh;
+   int    err;
+
+   skb = alloc_skb(NLMSG_SPACE(sizeof(driverLoaded)), GFP_KERNEL);
+   if (NULL == skb)
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                 "NLINK: skb alloc fail %s", __func__);
+      return;
+   }
+
+   nlh = (struct nlmsghdr *)skb->data;
+   nlh->nlmsg_pid = 0;  /* from kernel */
+   nlh->nlmsg_flags = 0;
+   nlh->nlmsg_seq = 0;
+   nlh->nlmsg_len = sizeof(driverLoaded);
+   memcpy(((char *)nlh) + sizeof(struct nlmsghdr),
+          driverLoaded,
+          sizeof(driverLoaded));
+   skb_put(skb, NLMSG_SPACE(sizeof(driverLoaded)));
+
+   /* sender is in group 1<<0 */
+   NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
+
+   /*multicast the message to all listening processes*/
+   err = netlink_broadcast(nl_srv_sock, skb, 0, 1, GFP_KERNEL);
+   if (!err)
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                 "NLINK: Ready Indication Send Fail %s", __func__);
+   }
+   return;
+}
+
+/*
+ * Send Net Link interface close indication to application daemon
+ * Each netlink message will have a message of type tAniMsgHdr inside.
+ */
+void nl_srv_nl_close_indication
+(
+   int pid
+)
+{
+   struct sk_buff *skb = NULL;
+   struct nlmsghdr *nlh;
+   int err;
+
+   skb = alloc_skb(sizeof(driverUnLoaded),GFP_KERNEL);
+   if (NULL == skb)
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                 "NLINK: skb alloc fail %s", __func__);
+      return;
+   }
+
+   nlh = (struct nlmsghdr *)skb->data;
+   nlh->nlmsg_pid = 0;  /* from kernel */
+   nlh->nlmsg_flags = 0;
+   nlh->nlmsg_seq = 0;
+   nlh->nlmsg_len = sizeof(driverUnLoaded);
+   memcpy(((char *)nlh) + sizeof(struct nlmsghdr),
+          driverUnLoaded,
+          sizeof(driverUnLoaded));
+   skb_put(skb, NLMSG_SPACE(sizeof(driverUnLoaded)));
+
+   /* sender is in group 1<<0 */
+   NETLINK_CB(skb).dst_group = 0;
+   err = netlink_unicast(nl_srv_sock, skb, pid, MSG_DONTWAIT);
+   if (!err)
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                 "NLINK: Close Indication Send Fail %s", __func__);
+   }
+
+   return;
+}
+#endif /* WLAN_KD_READY_NOTIFIER */
+
diff --git a/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c b/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c
index 8e3e579..ee5b30a 100644
--- a/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c
+++ b/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c
@@ -314,6 +314,9 @@
    pAdapterHandle = (struct hdd_context_s*)pAdapter;
    nl_srv_register(ANI_NL_MSG_PUMAC, ptt_sock_rx_nlink_msg);
    nl_srv_register(ANI_NL_MSG_PTT, ptt_sock_rx_nlink_msg);
+#ifdef WLAN_KD_READY_NOTIFIER
+   nl_srv_nl_ready_indication();
+#endif /* WLAN_KD_READY_NOTIFIER */
    return 0;
 }
 #endif //PTT_SOCK_SVC_ENABLE