Browse Source

qcacld-3.0: Add infrastructure for pktstats based on linkedlist

Proapagation from qcacld-2.0 to qcacld-3.0.

Currently pktstats are stored in static allocated memory. This
pkt stats can be accessed using
1) procEntry function
2) hal_proxy_daemon
If user access it using procEntry then read pointer is moved ahead
in static memory array because of which incomplete data goes when
queried using hal_proxy_daemon.
Fix this by maintaining the pktstats in link list. When the
request comes from hal_proxy_daemon, complete data is sent
to it from this link list

Change-Id: I09bbd03fe378b296e110ce52cc8cbeb8cf8d723d
CRs-Fixed: 958544
(cherry picked from commit c0d86fc4197383d0eb386e091cee5142a35b555a)
Himanshu Agarwal 8 years ago
parent
commit
46956a5aff

+ 1 - 0
core/cds/inc/cds_api.h

@@ -292,4 +292,5 @@ bool cds_is_5_mhz_enabled(void);
 bool cds_is_10_mhz_enabled(void);
 bool cds_is_sub_20_mhz_enabled(void);
 bool cds_is_self_recovery_enabled(void);
+void cds_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data);
 #endif /* if !defined __CDS_API_H */

+ 20 - 0
core/cds/src/cds_api.c

@@ -2290,3 +2290,23 @@ void cds_svc_fw_shutdown_ind(struct device *dev)
 {
 	hdd_svc_fw_shutdown_ind(dev);
 }
+
+/*
+ * cds_pkt_stats_to_logger_thread() - send pktstats to user
+ * @pl_hdr: Pointer to pl_hdr
+ * @pkt_dump: Pointer to pkt_dump data structure.
+ * @data: Pointer to data
+ *
+ * This function is used to send the pkt stats to SVC module.
+ *
+ * Return: None
+ */
+inline void cds_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump,
+						void *data)
+{
+	if (cds_get_ring_log_level(RING_ID_PER_PACKET_STATS) !=
+						WLAN_LOG_LEVEL_ACTIVE)
+		return;
+
+	wlan_pkt_stats_to_logger_thread(pl_hdr, pkt_dump, data);
+}

+ 3 - 0
core/utils/logging/inc/wlan_logging_sock_svc.h

@@ -77,4 +77,7 @@ static inline void wlan_report_log_completion(uint32_t is_fatal,
 }
 
 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data);
+
 #endif /* WLAN_LOGGING_SOCK_SVC_H */

+ 377 - 7
core/utils/logging/src/wlan_logging_sock_svc.c

@@ -40,6 +40,7 @@
 #include "pktlog_ac.h"
 #include <host_diag_core_event.h>
 #include "cds_utils.h"
+#include "host_diag_core_log.h"
 
 #define LOGGING_TRACE(level, args ...) \
 	QDF_TRACE(QDF_MODULE_ID_HDD, level, ## args)
@@ -49,10 +50,14 @@
 #define ANI_NL_MSG_LOG_TYPE 89
 #define ANI_NL_MSG_READY_IND_TYPE 90
 #define MAX_LOGMSG_LENGTH 4096
+#define MAX_PKTSTATS_LENGTH 2048
+#define MAX_PKTSTATS_BUFF   16
 
 #define HOST_LOG_DRIVER_MSG        0x001
 #define HOST_LOG_PER_PKT_STATS     0x002
 #define HOST_LOG_FW_FLUSH_COMPLETE 0x003
+#define DIAG_TYPE_LOGS                 1
+#define PTT_MSG_DIAG_CMDS_TYPE    0x5050
 
 struct log_msg {
 	struct list_head node;
@@ -67,6 +72,32 @@ struct log_msg {
 	char logbuf[MAX_LOGMSG_LENGTH];
 };
 
+/**
+ * struct packet_dump - This data structure contains the
+ * Tx/Rx packet stats
+ * @status: Status
+ * @type: Type
+ * @driver_ts: driver timestamp
+ * @fw_ts: fw timestamp
+ */
+struct packet_dump {
+	unsigned char status;
+	unsigned char type;
+	uint32_t driver_ts;
+	uint16_t fw_ts;
+} __attribute__((__packed__));
+
+/**
+ * struct pkt_stats_msg - This data structure contains the
+ * pkt stats node for link list
+ * @node: LinkList node
+ * @node: Pointer to skb
+ */
+struct pkt_stats_msg {
+	struct list_head node;
+	struct sk_buff *skb;
+};
+
 struct wlan_logging {
 	/* Log Fatal and ERROR to console */
 	bool log_fe_to_console;
@@ -96,10 +127,18 @@ struct wlan_logging {
 	bool is_active;
 	/* Flush completion check */
 	bool is_flush_complete;
+	/* paramaters  for pkt stats */
+	struct list_head pkt_stat_free_list;
+	struct list_head pkt_stat_filled_list;
+	struct pkt_stats_msg *pkt_stats_pcur_node;
+	unsigned int pkt_stat_drop_cnt;
+	spinlock_t pkt_stats_lock;
+	unsigned int pkt_stats_msg_idx;
 };
 
 static struct wlan_logging gwlan_logging;
 static struct log_msg *gplog_msg;
+static struct pkt_stats_msg *gpkt_stats_buffers;
 
 /* PID of the APP to log the message */
 static int gapp_pid = INVALID_PID;
@@ -411,6 +450,144 @@ int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length)
 	return 0;
 }
 
+/**
+ * pkt_stats_fill_headers() - This function adds headers to skb
+ * @skb: skb to which headers need to be added
+ *
+ * Return: 0 on success or Errno on failure
+ */
+static int pkt_stats_fill_headers(struct sk_buff *skb)
+{
+	struct host_log_pktlog_info cds_pktlog;
+	int cds_pkt_size = sizeof(struct host_log_pktlog_info);
+	tAniNlHdr msg_header;
+	int extra_header_len, nl_payload_len;
+	static int nlmsg_seq;
+	int diag_type;
+
+	qdf_mem_zero(&cds_pktlog, cds_pkt_size);
+	cds_pktlog.version = VERSION_LOG_WLAN_PKT_LOG_INFO_C;
+	cds_pktlog.buf_len = skb->len;
+	cds_pktlog.seq_no = gwlan_logging.pkt_stats_msg_idx++;
+	host_diag_log_set_code(&cds_pktlog, LOG_WLAN_PKT_LOG_INFO_C);
+	host_diag_log_set_length(&cds_pktlog.log_hdr, skb->len +
+				cds_pkt_size);
+
+	if (unlikely(skb_headroom(skb) < cds_pkt_size)) {
+		pr_err("VPKT [%d]: Insufficient headroom, head[%p], data[%p], req[%zu]",
+			__LINE__, skb->head, skb->data, sizeof(msg_header));
+		return -EIO;
+	}
+
+	qdf_mem_copy(skb_push(skb, cds_pkt_size),
+			&cds_pktlog, cds_pkt_size);
+
+	if (unlikely(skb_headroom(skb) < sizeof(int))) {
+		pr_err("VPKT [%d]: Insufficient headroom, head[%p], data[%p], req[%zu]",
+			__LINE__, skb->head, skb->data, sizeof(int));
+		return -EIO;
+	}
+
+	diag_type = DIAG_TYPE_LOGS;
+	qdf_mem_copy(skb_push(skb, sizeof(int)), &diag_type, sizeof(int));
+
+	extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr) +
+				sizeof(struct nlmsghdr);
+	nl_payload_len = extra_header_len + skb->len;
+
+	msg_header.nlh.nlmsg_type = ANI_NL_MSG_PUMAC;
+	msg_header.nlh.nlmsg_len = nl_payload_len;
+	msg_header.nlh.nlmsg_flags = NLM_F_REQUEST;
+	msg_header.nlh.nlmsg_pid = 0;
+	msg_header.nlh.nlmsg_seq = nlmsg_seq++;
+	msg_header.radio = 0;
+	msg_header.wmsg.type = PTT_MSG_DIAG_CMDS_TYPE;
+	msg_header.wmsg.length = cpu_to_be16(skb->len);
+
+	if (unlikely(skb_headroom(skb) < sizeof(msg_header))) {
+		pr_err("VPKT [%d]: Insufficient headroom, head[%p], data[%p], req[%zu]",
+			__LINE__, skb->head, skb->data, sizeof(msg_header));
+		return -EIO;
+	}
+
+	qdf_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header,
+			sizeof(msg_header));
+
+	return 0;
+}
+
+/**
+ * pktlog_send_per_pkt_stats_to_user() - This function is used to send the per
+ * packet statistics to the user
+ *
+ * This function is used to send the per packet statistics to the user
+ *
+ * Return: Success if the message is posted to user
+ */
+int pktlog_send_per_pkt_stats_to_user(void)
+{
+	int ret = -1;
+	struct pkt_stats_msg *pstats_msg;
+	unsigned long flags;
+	struct sk_buff *skb_new = NULL;
+	static int rate_limit;
+	bool free_old_skb = false;
+
+	while (!list_empty(&gwlan_logging.pkt_stat_filled_list)
+		&& !gwlan_logging.exit) {
+		skb_new = dev_alloc_skb(MAX_PKTSTATS_LENGTH);
+		if (skb_new == NULL) {
+			if (!rate_limit) {
+				pr_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n",
+					__func__, MAX_LOGMSG_LENGTH,
+					gwlan_logging.drop_count);
+			}
+			rate_limit = 1;
+			ret = -ENOMEM;
+			break;
+		}
+
+		spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
+
+		pstats_msg = (struct pkt_stats_msg *)
+			(gwlan_logging.pkt_stat_filled_list.next);
+		list_del_init(gwlan_logging.pkt_stat_filled_list.next);
+		spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
+
+		ret = pkt_stats_fill_headers(pstats_msg->skb);
+		if (ret < 0) {
+			pr_err("%s failed to fill headers %d\n", __func__, ret);
+			free_old_skb = true;
+			goto err;
+		}
+		ret = nl_srv_bcast(pstats_msg->skb);
+		if (ret < 0) {
+			pr_info("%s: Send Failed %d drop_count = %u\n",
+				__func__, ret,
+				++gwlan_logging.pkt_stat_drop_cnt);
+		} else {
+			ret = 0;
+		}
+err:
+	/*
+	 * Free old skb in case or error before assigning new skb
+	 * to the free list.
+	 */
+	if (free_old_skb)
+		dev_kfree_skb(pstats_msg->skb);
+
+		spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
+		pstats_msg->skb = skb_new;
+		list_add_tail(&pstats_msg->node,
+				&gwlan_logging.pkt_stat_free_list);
+		spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
+		ret = 0;
+	}
+
+	return ret;
+
+}
+
 static int send_filled_buffers_to_user(void)
 {
 	int ret = -1;
@@ -691,7 +868,7 @@ static int wlan_logging_proc_sock_rx_msg(struct sk_buff *skb)
 
 int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf)
 {
-	int i = 0;
+	int i = 0, j, pkt_stats_size;
 	unsigned long irq_flag;
 
 	gapp_pid = INVALID_PID;
@@ -720,6 +897,45 @@ int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf)
 	list_del_init(gwlan_logging.free_list.next);
 	spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
 
+	/* Initialize the pktStats data structure here */
+	pkt_stats_size = sizeof(struct pkt_stats_msg);
+	gpkt_stats_buffers = vmalloc(MAX_PKTSTATS_BUFF * pkt_stats_size);
+	if (!gpkt_stats_buffers) {
+		pr_err("%s: Could not allocate memory for Pkt stats\n",
+			__func__);
+		goto err1;
+	}
+	qdf_mem_zero(gpkt_stats_buffers,
+			MAX_PKTSTATS_BUFF * pkt_stats_size);
+
+	spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
+	gwlan_logging.pkt_stats_msg_idx = 0;
+	INIT_LIST_HEAD(&gwlan_logging.pkt_stat_free_list);
+	INIT_LIST_HEAD(&gwlan_logging.pkt_stat_filled_list);
+	spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
+
+
+	for (i = 0; i < MAX_PKTSTATS_BUFF; i++) {
+		gpkt_stats_buffers[i].skb = dev_alloc_skb(MAX_PKTSTATS_LENGTH);
+		if (gpkt_stats_buffers[i].skb == NULL) {
+			pr_err("%s: Memory alloc failed for skb", __func__);
+			/* free previously allocated skb and return */
+			for (j = 0; j < i ; j++)
+				dev_kfree_skb(gpkt_stats_buffers[j].skb);
+			goto err2;
+		}
+		spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
+		list_add(&gpkt_stats_buffers[i].node,
+			&gwlan_logging.pkt_stat_free_list);
+		spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
+	}
+	spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
+	gwlan_logging.pkt_stats_pcur_node = (struct pkt_stats_msg *)
+		(gwlan_logging.pkt_stat_free_list.next);
+	list_del_init(gwlan_logging.pkt_stat_free_list.next);
+	spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
+	/* Pkt Stats intialization done */
+
 	init_waitqueue_head(&gwlan_logging.wait_queue);
 	gwlan_logging.exit = false;
 	clear_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag);
@@ -731,12 +947,7 @@ int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf)
 	if (IS_ERR(gwlan_logging.thread)) {
 		pr_err("%s: Could not Create LogMsg Thread Controller",
 		       __func__);
-		spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
-		gwlan_logging.pcur_node = NULL;
-		spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
-		vfree(gplog_msg);
-		gplog_msg = NULL;
-		return -ENOMEM;
+		goto err3;
 	}
 	wake_up_process(gwlan_logging.thread);
 	gwlan_logging.is_active = true;
@@ -745,11 +956,31 @@ int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf)
 	nl_srv_register(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
 
 	return 0;
+
+err3:
+	for (i = 0; i < MAX_PKTSTATS_BUFF; i++) {
+		if (gpkt_stats_buffers[i].skb)
+			dev_kfree_skb(gpkt_stats_buffers[i].skb);
+	}
+err2:
+	spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
+	gwlan_logging.pkt_stats_pcur_node = NULL;
+	spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
+	vfree(gpkt_stats_buffers);
+	gpkt_stats_buffers = NULL;
+err1:
+	spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
+	gwlan_logging.pcur_node = NULL;
+	spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
+	vfree(gplog_msg);
+	gplog_msg = NULL;
+	return -ENOMEM;
 }
 
 int wlan_logging_sock_deactivate_svc(void)
 {
 	unsigned long irq_flag;
+	int i = 0;
 
 	if (!gplog_msg)
 		return 0;
@@ -775,14 +1006,29 @@ int wlan_logging_sock_deactivate_svc(void)
 	vfree(gplog_msg);
 	gplog_msg = NULL;
 
+	spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
+	gwlan_logging.pkt_stats_pcur_node = NULL;
+	gwlan_logging.pkt_stats_msg_idx = 0;
+	gwlan_logging.pkt_stat_drop_cnt = 0;
+	for (i = 0; i < MAX_PKTSTATS_BUFF; i++) {
+		if (gpkt_stats_buffers[i].skb)
+			dev_kfree_skb(gpkt_stats_buffers[i].skb);
+	}
+	spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
+
+	vfree(gpkt_stats_buffers);
+	gpkt_stats_buffers = NULL;
+
 	return 0;
 }
 
 int wlan_logging_sock_init_svc(void)
 {
 	spin_lock_init(&gwlan_logging.spin_lock);
+	spin_lock_init(&gwlan_logging.pkt_stats_lock);
 	gapp_pid = INVALID_PID;
 	gwlan_logging.pcur_node = NULL;
+	gwlan_logging.pkt_stats_pcur_node = NULL;
 
 	return 0;
 }
@@ -790,6 +1036,7 @@ int wlan_logging_sock_init_svc(void)
 int wlan_logging_sock_deinit_svc(void)
 {
 	gwlan_logging.pcur_node = NULL;
+	gwlan_logging.pkt_stats_pcur_node = NULL;
 	gapp_pid = INVALID_PID;
 
 	return 0;
@@ -867,4 +1114,127 @@ void wlan_flush_host_logs_for_fatal(void)
 	}
 }
 
+/**
+ * wlan_get_pkt_stats_free_node() - Get the free node for pkt stats
+ *
+ * This function is used to get the free node for pkt stats from
+ * free list/filles list
+ *
+ * Return: int
+ *
+ */
+static int wlan_get_pkt_stats_free_node(void)
+{
+	int ret = 0;
+
+	list_add_tail(&gwlan_logging.pkt_stats_pcur_node->node,
+			&gwlan_logging.pkt_stat_filled_list);
+
+	if (!list_empty(&gwlan_logging.pkt_stat_free_list)) {
+		/* Get buffer from free list */
+		gwlan_logging.pkt_stats_pcur_node =
+		(struct pkt_stats_msg *)(gwlan_logging.pkt_stat_free_list.next);
+		list_del_init(gwlan_logging.pkt_stat_free_list.next);
+	} else if (!list_empty(&gwlan_logging.pkt_stat_filled_list)) {
+		/* Get buffer from filled list. This condition will drop the
+		 * packet from being indicated to app
+		 */
+		gwlan_logging.pkt_stats_pcur_node =
+			(struct pkt_stats_msg *)
+				(gwlan_logging.pkt_stat_filled_list.next);
+		++gwlan_logging.pkt_stat_drop_cnt;
+		/* print every 64th drop count */
+		if (cds_is_multicast_logging() &&
+			(!(gwlan_logging.pkt_stat_drop_cnt % 0x40))) {
+			pr_err("%s: drop_count = %u\n",
+				__func__, gwlan_logging.pkt_stat_drop_cnt);
+		}
+		list_del_init(gwlan_logging.pkt_stat_filled_list.next);
+		ret = 1;
+	}
+
+	/* Reset the skb values, essential if dequeued from filled list */
+	skb_trim(gwlan_logging.pkt_stats_pcur_node->skb, 0);
+	return ret;
+}
+
+/**
+ * wlan_pkt_stats_to_logger_thread() - Add the pkt stats to SKB
+ * @pl_hdr: Pointer to pl_hdr
+ * @pkt_dump: Pointer to pkt_dump
+ * @data: Pointer to data
+ *
+ * This function adds the pktstats hdr and data to current
+ * skb node of free list.
+ *
+ * Return: None
+ */
+void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data)
+{
+	struct ath_pktlog_hdr *pktlog_hdr;
+	struct packet_dump *pkt_stats_dump;
+	int total_stats_len = 0;
+	bool wake_up_thread = false;
+	unsigned long flags;
+	struct sk_buff *ptr;
+	int hdr_size;
+
+	pktlog_hdr = (struct ath_pktlog_hdr *)pl_hdr;
+
+	if (pktlog_hdr == NULL) {
+		pr_err("%s : Invalid pkt_stats_header\n", __func__);
+		return;
+	}
+
+	pkt_stats_dump = (struct packet_dump *)pkt_dump;
+	if (pkt_stats_dump)
+		total_stats_len = sizeof(struct ath_pktlog_hdr) +
+					pktlog_hdr->size +
+					sizeof(struct packet_dump);
+	else
+		total_stats_len = sizeof(struct ath_pktlog_hdr) +
+					pktlog_hdr->size;
+
+	spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
+
+	if (!gwlan_logging.pkt_stats_pcur_node) {
+		spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
+		return;
+	}
+
+	/* Check if we can accommodate more log into current node/buffer */
+	hdr_size = sizeof(struct host_log_pktlog_info) +
+			sizeof(tAniNlHdr);
+	if ((total_stats_len +  hdr_size) >=
+		skb_tailroom(gwlan_logging.pkt_stats_pcur_node->skb)) {
+		wake_up_thread = true;
+		wlan_get_pkt_stats_free_node();
+	}
+
+	ptr = gwlan_logging.pkt_stats_pcur_node->skb;
+	qdf_mem_copy(skb_put(ptr,
+			sizeof(struct ath_pktlog_hdr)),
+			pktlog_hdr,
+			sizeof(struct ath_pktlog_hdr));
+
+	if (pkt_stats_dump)
+		qdf_mem_copy(skb_put(ptr,
+				sizeof(struct packet_dump)),
+				pkt_stats_dump,
+				sizeof(struct packet_dump));
+
+	qdf_mem_copy(skb_put(ptr,
+				pktlog_hdr->size),
+				data, pktlog_hdr->size);
+
+	spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
+
+	/* Wakeup logger thread */
+	if (true == wake_up_thread) {
+		set_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag);
+		wake_up_interruptible(&gwlan_logging.wait_queue);
+	}
+}
+
+
 #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */

+ 0 - 132
core/utils/pktlog/linux_ac.c

@@ -543,138 +543,6 @@ static int pktlog_release(struct inode *i, struct file *f)
 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
 #endif
 
-/**
- * pktlog_send_per_pkt_stats_to_user() - This function is used to send the per
- * packet statistics to the user
- *
- * This function is used to send the per packet statistics to the user
- *
- * Return: Success if the message is posted to user
- *
- */
-int pktlog_send_per_pkt_stats_to_user(void)
-{
-	ssize_t ret_val;
-	struct host_log_pktlog_info *pktlog = NULL;
-	ol_txrx_pdev_handle txrx_pdev =
-		cds_get_context(QDF_MODULE_ID_TXRX);
-	struct ath_pktlog_info *pl_info;
-	bool read_complete;
-	uint32_t num_bytes_read = 0;
-
-	/*
-	 * We do not want to do this packet stats related processing when
-	 * packet log tool is run. i.e., we want this processing to be
-	 * done only when start logging command of packet stats is initiated.
-	 */
-	if ((cds_get_ring_log_level(RING_ID_PER_PACKET_STATS) <
-				WLAN_LOG_LEVEL_ACTIVE)) {
-		printk(PKTLOG_TAG " %s: Shouldnt happen. Logging not started\n",
-				__func__);
-		return -EINVAL;
-	}
-
-	if (!txrx_pdev) {
-		printk(PKTLOG_TAG " %s: Invalid TxRx handle\n", __func__);
-		return -EINVAL;
-	}
-
-	pl_info = txrx_pdev->pl_dev->pl_info;
-
-	if (!pl_info || !pl_info->buf) {
-		printk(PKTLOG_TAG " %s: Shouldnt happen. pl_info is invalid\n",
-				__func__);
-		return -EINVAL;
-	}
-
-	if (pl_info->buf->rd_offset == -1) {
-		printk(PKTLOG_TAG " %s: Shouldnt happen. No write yet!\n",
-			__func__);
-		return -EINVAL;
-	}
-
-	do {
-		pktlog = (struct host_log_pktlog_info *)
-			qdf_mem_malloc(sizeof(struct host_log_pktlog_info) +
-					VOS_LOG_PKT_LOG_SIZE);
-		if (!pktlog) {
-			printk(PKTLOG_TAG " %s: Memory allocation failed\n",
-				__func__);
-			return -ENOMEM;
-		}
-
-		host_diag_log_set_code(pktlog, LOG_WLAN_PKT_LOG_INFO_C);
-
-		pktlog->buf_len = 0;
-		pktlog->version = VERSION_LOG_WLAN_PKT_LOG_INFO_C;
-
-		/*
-		 * @ret_val: ret_val gives the actual data read from the buffer.
-		 * When there is no more data to read, this value will be zero
-		 * @offset: offset in the ring buffer. Initially it is zero and
-		 * is incremented during every read based on number of bytes
-		 * read
-		 */
-		ret_val = pktlog_read_proc_entry(pktlog->buf,
-				VOS_LOG_PKT_LOG_SIZE,
-				&pl_info->buf->offset,
-				pl_info, &read_complete);
-		if (ret_val) {
-			int index = 0;
-			struct ath_pktlog_hdr *temp;
-			while (1) {
-				if ((ret_val - index) <
-						sizeof(struct ath_pktlog_hdr)) {
-					/* Partial header */
-					pl_info->buf->offset -=
-							(ret_val - index);
-					ret_val = index;
-					break;
-				}
-				temp = (struct ath_pktlog_hdr *)
-					(pktlog->buf + index);
-				if ((ret_val - index) < (temp->size +
-					sizeof(struct ath_pktlog_hdr))) {
-					/* Partial record payload */
-					pl_info->buf->offset -=
-							(ret_val - index);
-					ret_val = index;
-					break;
-				}
-				index += temp->size +
-					sizeof(struct ath_pktlog_hdr);
-			}
-		}
-
-		/* Data will include message index/seq number and buf length */
-		pktlog->buf_len = ret_val;
-		if (ret_val) {
-			host_diag_log_set_length(pktlog, ret_val +
-					sizeof(struct host_log_pktlog_info));
-			pktlog->seq_no = pl_info->buf->msg_index++;
-			WLAN_HOST_DIAG_LOG_REPORT(pktlog);
-		} else {
-			qdf_mem_free(pktlog);
-		}
-		num_bytes_read += ret_val;
-
-		/*
-		 * If the logger thread is scheduled late and the proc entry
-		 * is having too much data to be read, we might start to starve
-		 * the other threads if we continuously keep reading the proc
-		 * entry. So, having a threshold to break this read from proc
-		 * entry.
-		 */
-		if (num_bytes_read > HOST_LOG_PKT_LOG_THRESHOLD) {
-			read_complete = true;
-			printk(PKTLOG_TAG " %s: Break read to prevent starve\n",
-				__func__);
-		}
-	} while (read_complete == false);
-
-	return 0;
-}
-
 /**
  * pktlog_read_proc_entry() - This function is used to read data from the
  * proc entry into the readers buffer

+ 17 - 9
core/utils/pktlog/pktlog_internal.c

@@ -206,15 +206,6 @@ char *pktlog_getbuf(struct ol_pktlog_dev_t *pl_dev,
 		PKTLOG_UNLOCK(pl_info);
 	}
 
-	/*
-	 * We do not want to do this packet stats related processing when
-	 * packet log tool is run. i.e., we want this processing to be
-	 * done only when start logging command of packet stats is initiated.
-	 */
-	if (cds_get_ring_log_level(RING_ID_PER_PACKET_STATS) ==
-			WLAN_LOG_LEVEL_ACTIVE)
-		pktlog_check_threshold(pl_info, log_size);
-
 	return plarg.buf;
 }
 
@@ -426,6 +417,9 @@ A_STATUS process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, void *data)
 					((void *)data +
 					 sizeof(struct ath_pktlog_hdr)),
 					 pl_hdr.size);
+		pl_hdr.size = log_size;
+		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
+						txdesc_hdr_ctl);
 	}
 
 	if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) {
@@ -439,6 +433,8 @@ A_STATUS process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, void *data)
 		qdf_mem_copy(txstat_log.ds_status,
 			     ((void *)data + sizeof(struct ath_pktlog_hdr)),
 			     pl_hdr.size);
+		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
+						txstat_log.ds_status);
 	}
 	return A_OK;
 }
@@ -544,6 +540,9 @@ A_STATUS process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, void *data)
 		qdf_assert(txctl_log.txdesc_hdr_ctl);
 		qdf_mem_copy(txctl_log.txdesc_hdr_ctl, &txctl_log.priv,
 			     sizeof(txctl_log.priv));
+		pl_hdr.size = log_size;
+		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
+						txctl_log.txdesc_hdr_ctl);
 		/* Add Protocol information and HT specific information */
 	}
 
@@ -557,6 +556,8 @@ A_STATUS process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, void *data)
 		qdf_mem_copy(txstat_log.ds_status,
 			     ((void *)data + sizeof(struct ath_pktlog_hdr)),
 			     pl_hdr.size);
+		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
+						txstat_log.ds_status);
 	}
 
 	if (pl_hdr.log_type == PKTLOG_TYPE_TX_MSDU_ID) {
@@ -576,6 +577,8 @@ A_STATUS process_tx_info(struct ol_txrx_pdev_t *txrx_pdev, void *data)
 			     sizeof(pl_msdu_info.priv.msdu_id_info));
 		qdf_mem_copy(pl_msdu_info.ath_msdu_info, &pl_msdu_info.priv,
 			     sizeof(pl_msdu_info.priv));
+		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
+						pl_msdu_info.ath_msdu_info);
 	}
 	return A_OK;
 }
@@ -635,6 +638,8 @@ A_STATUS process_rx_info_remote(void *pdev, void *data)
 							   log_size, &pl_hdr);
 		qdf_mem_copy(rxstat_log.rx_desc, (void *)rx_desc +
 			     sizeof(struct htt_host_fw_desc_base), pl_hdr.size);
+		cds_pkt_stats_to_logger_thread(&pl_hdr, NULL,
+						rxstat_log.rx_desc);
 		msdu = qdf_nbuf_next(msdu);
 	}
 	return A_OK;
@@ -684,6 +689,7 @@ A_STATUS process_rx_info(void *pdev, void *data)
 
 	qdf_mem_copy(rxstat_log.rx_desc,
 		     (void *)data + sizeof(struct ath_pktlog_hdr), pl_hdr.size);
+	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc);
 
 	return A_OK;
 }
@@ -748,6 +754,7 @@ A_STATUS process_rate_find(void *pdev, void *data)
 	qdf_mem_copy(rcf_log.rcFind,
 				 ((char *)data + sizeof(struct ath_pktlog_hdr)),
 				 pl_hdr.size);
+	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind);
 
 	return A_OK;
 }
@@ -880,6 +887,7 @@ A_STATUS process_rate_update(void *pdev, void *data)
 	qdf_mem_copy(rcu_log.txRateCtrl,
 		     ((char *)data + sizeof(struct ath_pktlog_hdr)),
 		     pl_hdr.size);
+	cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl);
 	return A_OK;
 }
 #endif /*REMOVE_PKT_LOG */