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