[qca-nss-drv] Add support for async messaging in virt_if

Add support for asynchronous messaging in virt_if and
dynamic_interface.

CRs-Fixed: 853868
Change-Id: I06c0dc74d8fce74cab50d565560590351759a8d3
Signed-off-by: Sundarajan Srinivasan <sundaraj@codeaurora.org>
diff --git a/nss_stats.c b/nss_stats.c
index 71fd9ac..d5ed3e5 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -34,6 +34,8 @@
  */
 extern struct nss_top_instance nss_top_main;
 
+extern int32_t nss_tx_rx_virt_if_copy_stats(int32_t if_num, int i, char *line);
+
 uint64_t stats_shadow_pppoe_except[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_PPPOE_EXCEPTION_EVENT_MAX];
 
 /*
@@ -1783,6 +1785,87 @@
 }
 
 /*
+ * nss_stats_tx_rx_virt_if_read()
+ *	Read tx_rx_virt_if statistics
+ */
+static ssize_t nss_stats_tx_rx_virt_if_read(struct file *fp, char __user *ubuf,
+						size_t sz, loff_t *ppos)
+{
+	struct nss_stats_data *data = fp->private_data;
+	int32_t if_num = NSS_DYNAMIC_IF_START;
+	int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES;
+	size_t bytes = 0;
+	ssize_t bytes_read = 0;
+	char line[80];
+	int start, end;
+
+	if (data) {
+		if_num = data->if_num;
+	}
+
+	if (if_num > max_if_num) {
+		return 0;
+	}
+
+	for (; if_num < max_if_num; if_num++) {
+		if (nss_dynamic_interface_get_type(if_num) != NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED)
+			continue;
+
+		bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num);
+		if ((bytes_read + bytes) > sz)
+			break;
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto end;
+		}
+
+		bytes_read += bytes;
+
+		start = 0;
+		end = 7;
+		while (bytes_read < sz && start < end) {
+			bytes = nss_tx_rx_virt_if_copy_stats(if_num, start, line);
+			if (!bytes)
+				break;
+
+			if ((bytes_read + bytes) > sz)
+				break;
+
+			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+				bytes_read = -EFAULT;
+				goto end;
+			}
+
+			bytes_read += bytes;
+			start++;
+		}
+
+		bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num);
+		if (bytes_read > (sz - bytes))
+			break;
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto end;
+		}
+
+		bytes_read += bytes;
+	}
+
+	if (bytes_read > 0) {
+		*ppos = bytes_read;
+	}
+
+	if (data) {
+		data->if_num = if_num;
+	}
+
+end:
+	return bytes_read;
+}
+
+/*
  * nss_stats_open()
  */
 static int nss_stats_open(struct inode *inode, struct file *filp)
@@ -1893,6 +1976,8 @@
 
 NSS_STATS_DECLARE_FILE_OPERATIONS(virt_if)
 
+NSS_STATS_DECLARE_FILE_OPERATIONS(tx_rx_virt_if)
+
 /*
  * wifi_stats_ops
  */
@@ -2097,6 +2182,13 @@
 		return;
 	}
 
+	nss_top_main.tx_rx_virt_if_dentry = debugfs_create_file("tx_rx_virt_if", 0400,
+						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_tx_rx_virt_if_ops);
+	if (unlikely(nss_top_main.virt_if_dentry == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/tx_rx_virt_if file in debugfs");
+		return;
+	}
+
 	nss_log_init();
 }