wlan: Send broadcast logging service ready indication

Send broadcast logging service ready indication to any running
application in order to inform the applications to register
themselves so that logs are routed to the newly registered
application.

Change-Id: Ic1665da3e74c02866defccc7b1f3e35d1ba2bccf
CRs-Fixed: 689563
diff --git a/CORE/SVC/src/logging/wlan_logging_sock_svc.c b/CORE/SVC/src/logging/wlan_logging_sock_svc.c
index e65ba1c..1290061 100644
--- a/CORE/SVC/src/logging/wlan_logging_sock_svc.c
+++ b/CORE/SVC/src/logging/wlan_logging_sock_svc.c
@@ -46,6 +46,7 @@
 /* Global variables */
 
 #define ANI_NL_MSG_LOG_TYPE 89
+#define ANI_NL_MSG_READY_IND_TYPE 90
 #define INVALID_PID -1
 
 #define MAX_LOGMSG_LENGTH 4096
@@ -95,6 +96,64 @@
 
 /* PID of the APP to log the message */
 static int gapp_pid = INVALID_PID;
+static char wlan_logging_ready[] = "WLAN LOGGING READY";
+
+/*
+ * Broadcast Logging service ready indication to any Logging application
+ * Each netlink message will have a message of type tAniMsgHdr inside.
+ */
+void wlan_logging_srv_nl_ready_indication(void)
+{
+	struct sk_buff *skb = NULL;
+	struct nlmsghdr *nlh;
+	tAniNlHdr *wnl = NULL;
+	int payload_len;
+	int    err;
+	static int rate_limit;
+
+	payload_len = sizeof(tAniHdr) + sizeof(wlan_logging_ready) +
+		sizeof(wnl->radio);
+	skb = dev_alloc_skb(NLMSG_SPACE(payload_len));
+	if (NULL == skb) {
+		if (!rate_limit) {
+			LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR,
+					"NLINK: skb alloc fail %s", __func__);
+		}
+		rate_limit = 1;
+		return;
+	}
+	rate_limit = 0;
+
+	nlh = nlmsg_put(skb, 0, 0, ANI_NL_MSG_LOG, payload_len,
+			NLM_F_REQUEST);
+	if (NULL == nlh) {
+		LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR,
+				"%s: nlmsg_put() failed for msg size[%d]",
+				__func__, payload_len);
+		kfree_skb(skb);
+		return;
+	}
+
+	wnl = (tAniNlHdr *) nlh;
+	wnl->radio = 0;
+	wnl->wmsg.type = ANI_NL_MSG_READY_IND_TYPE;
+	wnl->wmsg.length = sizeof(wlan_logging_ready);
+	memcpy((char*)&wnl->wmsg + sizeof(tAniHdr),
+			wlan_logging_ready,
+			sizeof(wlan_logging_ready));
+
+	/* sender is in group 1<<0 */
+	NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
+
+	/*multicast the message to all listening processes*/
+	err = nl_srv_bcast(skb);
+	if (err) {
+		LOGGING_TRACE(VOS_TRACE_LEVEL_INFO_LOW,
+			"NLINK: Ready Indication Send Fail %s, err %d",
+			__func__, err);
+	}
+	return;
+}
 
 /* Utility function to send a netlink message to an application
  * in user space
@@ -303,8 +362,19 @@
 	spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
 
 	/* Wakeup logger thread */
-	if ((true == wake_up_thread) && (gapp_pid != INVALID_PID))
-		wake_up_interruptible(&gwlan_logging.wait_queue);
+	if ((true == wake_up_thread)) {
+		/* If there is logger app registered wakeup the logging
+                 * thread Else broadcast a Ready Indication message,
+                 * apps which are waiting on this message can
+                 * register for the logs.
+                 */
+		if ( (gapp_pid != INVALID_PID)) {
+			wake_up_interruptible(&gwlan_logging.wait_queue);
+		}
+		else {
+			wlan_logging_srv_nl_ready_indication();
+		}
+	}
 
 	if ((gapp_pid != INVALID_PID)
 		&& gwlan_logging.log_fe_to_console
@@ -393,6 +463,7 @@
 			skb = NULL;
 			gapp_pid = INVALID_PID;
 			clear_default_logtoapp_log_level();
+			wlan_logging_srv_nl_ready_indication();
 		} else {
 			skb = NULL;
 			ret = 0;
@@ -559,6 +630,8 @@
 
 	nl_srv_register(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
 
+	//Broadcast SVC ready message to logging app/s running
+	wlan_logging_srv_nl_ready_indication();
 	pr_info("%s: Activated wlan_logging svc\n", __func__);
 	return 0;
 }