1 /*
2 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /**
18 * DOC: wlan_hdd_sysfs_txrx_stats_console.c
19 *
20 * implementation for creating sysfs files:
21 *
22 * txrx_stats
23 */
24
25 #include <wlan_hdd_includes.h>
26 #include "osif_psoc_sync.h"
27 #include <wlan_hdd_sysfs.h>
28 #include <wlan_hdd_sysfs_txrx_stats_console.h>
29 #include <cds_api.h>
30 #include <qdf_status.h>
31
32 #ifdef WLAN_SYSFS_DP_STATS
33
34 #define HDD_WLAN_SYSFS_TXRX_STATS_USER_CMD_SIZE (10)
35 #define SYSFS_INPUT_BUF_SIZE PAGE_SIZE
36
37 /*
38 * __hdd_wlan_txrx_stats_store() - Calls into dp layer to
39 * update the sysfs config values.
40 * @hdd_ctx: hdd context
41 * @buf: input buffer from user space
42 * @count: input buffer size
43 *
44 * Return: Return the size of input buffer.
45 */
46 static ssize_t
__hdd_wlan_txrx_stats_store(struct hdd_context * hdd_ctx,const char * buf,size_t count)47 __hdd_wlan_txrx_stats_store(struct hdd_context *hdd_ctx,
48 const char *buf, size_t count)
49 {
50 char buf_local[HDD_WLAN_SYSFS_TXRX_STATS_USER_CMD_SIZE + 1];
51 char *sptr, *token;
52 uint32_t stat_type_requested;
53 uint32_t mac_id;
54 int ret;
55 ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
56
57 if (!soc) {
58 hdd_err_rl("soc is NULL");
59 return -EINVAL;
60 }
61
62 if (count > HDD_WLAN_SYSFS_TXRX_STATS_USER_CMD_SIZE)
63 return -EINVAL;
64
65 if (!wlan_hdd_validate_modules_state(hdd_ctx))
66 return -EINVAL;
67
68 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
69 buf, count);
70
71 if (ret)
72 return -EINVAL;
73
74 sptr = buf_local;
75 /* get mac id */
76 token = strsep(&sptr, " ");
77 if (!token)
78 return -EINVAL;
79 if (kstrtou32(token, 0, &stat_type_requested))
80 return -EINVAL;
81
82 /* get stat type requested */
83 token = strsep(&sptr, " ");
84 if (!token)
85 return -EINVAL;
86 if (kstrtou32(token, 0, &mac_id))
87 return -EINVAL;
88
89 if (!soc->ops->cmn_drv_ops->txrx_sysfs_set_stat_type) {
90 hdd_err("txrx_sysfs_set_stat_type is NULL");
91 return -EINVAL;
92 }
93
94 soc->ops->cmn_drv_ops->txrx_sysfs_set_stat_type(soc,
95 stat_type_requested,
96 mac_id);
97
98 return count;
99 }
100
101 /*
102 * __hdd_wlan_txrx_stats_show() - Calls into dp to fill stats.
103 * @buf: output buffer
104 *
105 * Return: output buffer size.
106 */
107 static ssize_t
__hdd_wlan_txrx_stats_show(char * buf)108 __hdd_wlan_txrx_stats_show(char *buf)
109 {
110 uint32_t size_of_output = 0;
111 ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
112
113 if (!soc) {
114 hdd_err_rl("hdd dp_soc cds_get_context returned NULL");
115 return -EINVAL;
116 }
117
118 if (!soc->ops->cmn_drv_ops->txrx_sysfs_fill_stats) {
119 hdd_err_rl("txrx_sysfs_fill_stats is NULL");
120 return -EINVAL;
121 }
122 soc->ops->cmn_drv_ops->txrx_sysfs_fill_stats(soc,
123 buf,
124 SYSFS_INPUT_BUF_SIZE);
125 size_of_output = strlen(buf);
126 return size_of_output;
127 }
128
129 /*
130 * hdd_sysfs_dp_txrx_stats_show() - Registered as sysfs show function.
131 * @kobj: kernel object
132 * @att: kobject attribute
133 * @buf: output buffer to be filled
134 *
135 * Return: Returns the length of the output buffer.
136 */
137 static ssize_t
hdd_sysfs_dp_txrx_stats_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)138 hdd_sysfs_dp_txrx_stats_show(struct kobject *kobj,
139 struct kobj_attribute *attr,
140 char *buf)
141 {
142 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
143 struct osif_psoc_sync *psoc_sync = NULL;
144 ssize_t length = 0;
145 ssize_t errno = 0;
146
147 errno = wlan_hdd_validate_context(hdd_ctx);
148 if (errno)
149 return errno;
150
151 errno = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync);
152 if (errno)
153 return errno;
154
155 length = __hdd_wlan_txrx_stats_show(buf);
156
157 osif_psoc_sync_op_stop(psoc_sync);
158
159 return length;
160 }
161
162 /*
163 * hdd_sysfs_dp_txrx_stats_store() - Registered as sysfs write function.
164 * @kobj: kernel object
165 * @att: kobject attribute
166 * @buf: input buffer from user space
167 * @count: size of the input buffer
168 *
169 * Return: Returns the length of the input buffer.
170 */
171 static ssize_t
hdd_sysfs_dp_txrx_stats_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)172 hdd_sysfs_dp_txrx_stats_store(struct kobject *kobj,
173 struct kobj_attribute *attr,
174 const char *buf,
175 size_t count)
176 {
177 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
178 struct osif_psoc_sync *psoc_sync = NULL;
179 ssize_t errno = 0;
180
181 errno = wlan_hdd_validate_context(hdd_ctx);
182 if (errno)
183 return errno;
184
185 errno = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync);
186 if (errno)
187 return errno;
188
189 errno = __hdd_wlan_txrx_stats_store(hdd_ctx, buf, count);
190
191 osif_psoc_sync_op_stop(psoc_sync);
192
193 return errno;
194 }
195
196 static struct kobj_attribute dp_txrx_stats_attribute =
197 __ATTR(txrx_stats, 0664, hdd_sysfs_dp_txrx_stats_show,
198 hdd_sysfs_dp_txrx_stats_store);
199
200 /*
201 * hdd_sysfs_dp_txrx_stats_sysfs_create() - Initialize sysfs file.
202 * @driver_kobject: driver kobject
203 *
204 * Return: return sysfs int val.
205 */
hdd_sysfs_dp_txrx_stats_sysfs_create(struct kobject * driver_kobject)206 int hdd_sysfs_dp_txrx_stats_sysfs_create(struct kobject *driver_kobject)
207 {
208 int error = 0;
209
210 if (!driver_kobject) {
211 hdd_err("could not get driver kobject");
212 return -EINVAL;
213 }
214
215 error = sysfs_create_file(driver_kobject,
216 &dp_txrx_stats_attribute.attr);
217
218 if (error)
219 hdd_err("failed to create txrx_stats sysfs file");
220
221 return error;
222 }
223
224 /*
225 * hdd_sysfs_dp_txrx_stats_sysfs_destroy() - Sysfs deinitialize.
226 * @driver_kobject: driver kobject
227 *
228 * Return: void
229 */
230 void
hdd_sysfs_dp_txrx_stats_sysfs_destroy(struct kobject * driver_kobject)231 hdd_sysfs_dp_txrx_stats_sysfs_destroy(struct kobject *driver_kobject)
232 {
233 if (!driver_kobject) {
234 hdd_err("failed to get driver kobject");
235 return;
236 }
237
238 sysfs_remove_file(driver_kobject, &dp_txrx_stats_attribute.attr);
239 }
240 #endif /* WLAN_SYSFS_DP_STATS */
241