1 /*
2  * Copyright (c) 2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  *  DOC: wlan_hdd_sysfs_mem_stats.c
21  *
22  *  Implementation to add sysfs node wlan_mem_stats
23  *
24  */
25 
26 #include <wlan_hdd_includes.h>
27 #include "osif_psoc_sync.h"
28 #include <wlan_hdd_sysfs.h>
29 #include <qdf_mem.h>
30 #include <wlan_hdd_sysfs_mem_stats.h>
31 
__hdd_wlan_mem_stats_show(char * buf)32 static ssize_t __hdd_wlan_mem_stats_show(char *buf)
33 {
34 	return scnprintf(buf, PAGE_SIZE,
35 			 "DMA = %d HEAP = %d SKB = %d SKB_MAX = %d\n",
36 			 qdf_dma_mem_stats_read(),
37 			 qdf_heap_mem_stats_read(),
38 			 qdf_skb_total_mem_stats_read(),
39 			 qdf_skb_max_mem_stats_read());
40 }
41 
__hdd_wlan_dp_mem_stats_show(char * buf)42 static ssize_t __hdd_wlan_dp_mem_stats_show(char *buf)
43 {
44 	int32_t len = 0;
45 
46 	len += scnprintf(buf + len, PAGE_SIZE,
47 			 "TX_NBUF_MEM = %d MAX_TX_NBUF_MEM = %d "
48 			 "RX_NBUF_MEM = %d MAX_RX_NBUF_MEM = %d "
49 			 "TX_NBUF_CNT = %d MAX_TX_NBUF_CNT = %d "
50 			 "RX_NBUF_CNT = %d MAX_RX_NBUF_CNT = %d "
51 			 "PENDING_TX_DESCS = %d MAX_PENDING_TX_DESCS = %d\n",
52 			 qdf_dp_tx_skb_mem_stats_read(),
53 			 qdf_dp_tx_skb_max_mem_stats_read(),
54 			 qdf_dp_rx_skb_mem_stats_read(),
55 			 qdf_dp_rx_skb_max_mem_stats_read(),
56 			 qdf_mem_dp_tx_skb_cnt_read(),
57 			 qdf_mem_dp_tx_skb_max_cnt_read(),
58 			 qdf_mem_dp_rx_skb_cnt_read(),
59 			 qdf_mem_dp_rx_skb_max_cnt_read(),
60 			 qdf_mem_tx_desc_cnt_read(),
61 			 qdf_mem_tx_desc_max_read());
62 	return len;
63 }
64 
hdd_wlan_mem_stats_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)65 static ssize_t hdd_wlan_mem_stats_show(struct kobject *kobj,
66 				       struct kobj_attribute *attr,
67 				       char *buf)
68 {
69 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
70 	struct osif_psoc_sync *psoc_sync;
71 	ssize_t length;
72 	int errno;
73 
74 	errno = wlan_hdd_validate_context(hdd_ctx);
75 	if (errno)
76 		return errno;
77 
78 	errno = osif_psoc_sync_op_start(hdd_ctx->parent_dev, &psoc_sync);
79 	if (errno)
80 		return errno;
81 
82 	length = __hdd_wlan_mem_stats_show(buf);
83 	if (psoc_sync)
84 		osif_psoc_sync_op_stop(psoc_sync);
85 
86 	return length;
87 }
88 
hdd_wlan_dp_mem_stats_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)89 static ssize_t hdd_wlan_dp_mem_stats_show(struct kobject *kobj,
90 					  struct kobj_attribute *attr,
91 					  char *buf)
92 {
93 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
94 	struct osif_psoc_sync *psoc_sync;
95 	ssize_t length;
96 	int errno;
97 
98 	errno = wlan_hdd_validate_context(hdd_ctx);
99 	if (errno)
100 		return errno;
101 
102 	errno = osif_psoc_sync_op_start(hdd_ctx->parent_dev, &psoc_sync);
103 	if (errno)
104 		return errno;
105 
106 	length = __hdd_wlan_dp_mem_stats_show(buf);
107 	if (psoc_sync)
108 		osif_psoc_sync_op_stop(psoc_sync);
109 
110 	return length;
111 }
112 
113 static struct kobj_attribute mem_stats_attribute =
114 	__ATTR(wlan_mem_stats, 0440, hdd_wlan_mem_stats_show, NULL);
115 
116 static struct kobj_attribute mem_dp_stats_attribute =
117 	__ATTR(wlan_dp_mem_stats, 0440, hdd_wlan_dp_mem_stats_show, NULL);
118 
hdd_sysfs_mem_stats_create(struct kobject * wlan_kobject)119 int hdd_sysfs_mem_stats_create(struct kobject *wlan_kobject)
120 {
121 	int error;
122 
123 	if (!wlan_kobject) {
124 		hdd_err("Could not get wlan kobject!");
125 		return -EINVAL;
126 	}
127 	error = sysfs_create_file(wlan_kobject, &mem_stats_attribute.attr);
128 	if (error) {
129 		hdd_err("Failed to create sysfs file wlan_mem_stats");
130 		return -EINVAL;
131 	}
132 	error = sysfs_create_file(wlan_kobject, &mem_dp_stats_attribute.attr);
133 	if (error) {
134 		hdd_err("Failed to create sysfs file wlan_dp_mem_stats");
135 		sysfs_remove_file(wlan_kobject, &mem_stats_attribute.attr);
136 		return -EINVAL;
137 	}
138 
139 	qdf_mem_stats_init();
140 
141 	return error;
142 }
143 
hdd_sysfs_mem_stats_destroy(struct kobject * wlan_kobject)144 void hdd_sysfs_mem_stats_destroy(struct kobject *wlan_kobject)
145 {
146 	if (!wlan_kobject) {
147 		hdd_err("Could not get wlan kobject!");
148 		return;
149 	}
150 	sysfs_remove_file(wlan_kobject, &mem_dp_stats_attribute.attr);
151 	sysfs_remove_file(wlan_kobject, &mem_stats_attribute.attr);
152 }
153 
154