1 /*
2  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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_dp_tx_delay_stats.c
19  *
20  * implementation for creating sysfs files:
21  *
22  * dp_tx_delay_stats
23  */
24 #include <wlan_hdd_includes.h>
25 #include "osif_vdev_sync.h"
26 #include "wlan_hdd_object_manager.h"
27 #include <wlan_hdd_sysfs.h>
28 #include <wlan_hdd_sysfs_dp_tx_delay_stats.h>
29 #include <cdp_txrx_host_stats.h>
30 
31 static ssize_t
__hdd_sysfs_dp_tx_delay_stats_show(struct net_device * net_dev,char * buf)32 __hdd_sysfs_dp_tx_delay_stats_show(struct net_device *net_dev,
33 				   char *buf)
34 {
35 	struct hdd_adapter *adapter = netdev_priv(net_dev);
36 	ol_txrx_soc_handle dp_soc = cds_get_context(QDF_MODULE_ID_SOC);
37 	uint8_t value;
38 	int ret;
39 
40 	if (hdd_validate_adapter(adapter) || !dp_soc)
41 		return -EINVAL;
42 
43 	ret = wlan_hdd_validate_context(adapter->hdd_ctx);
44 	if (ret)
45 		return ret;
46 
47 	if (!wlan_hdd_validate_modules_state(adapter->hdd_ctx))
48 		return -EINVAL;
49 
50 	value = cdp_vdev_is_tx_delay_stats_enabled(dp_soc,
51 						   adapter->deflink->vdev_id);
52 
53 	hdd_debug("vdev_id: %d tx_delay_stats: %d",
54 		  adapter->deflink->vdev_id, value);
55 
56 	return scnprintf(buf, PAGE_SIZE, "%d\n", value);
57 }
58 
hdd_sysfs_dp_tx_delay_stats_show(struct device * dev,struct device_attribute * attr,char * buf)59 static ssize_t hdd_sysfs_dp_tx_delay_stats_show(struct device *dev,
60 						struct device_attribute *attr,
61 						char *buf)
62 {
63 	struct net_device *net_dev = container_of(dev, struct net_device, dev);
64 	struct osif_vdev_sync *vdev_sync;
65 	ssize_t err_size;
66 
67 	err_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
68 	if (err_size)
69 		return err_size;
70 
71 	err_size = __hdd_sysfs_dp_tx_delay_stats_show(net_dev, buf);
72 
73 	osif_vdev_sync_op_stop(vdev_sync);
74 
75 	return err_size;
76 }
77 
78 static ssize_t
__hdd_sysfs_dp_tx_delay_stats_store(struct net_device * net_dev,const char * buf,size_t count)79 __hdd_sysfs_dp_tx_delay_stats_store(struct net_device *net_dev, const char *buf,
80 				    size_t count)
81 {
82 	struct hdd_adapter *adapter = netdev_priv(net_dev);
83 	char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
84 	ol_txrx_soc_handle dp_soc = cds_get_context(QDF_MODULE_ID_SOC);
85 	char *sptr, *token;
86 	uint8_t value;
87 	int ret;
88 
89 	if (hdd_validate_adapter(adapter) || !dp_soc)
90 		return -EINVAL;
91 
92 	ret = wlan_hdd_validate_context(adapter->hdd_ctx);
93 	if (ret)
94 		return ret;
95 
96 	if (!wlan_hdd_validate_modules_state(adapter->hdd_ctx))
97 		return -EINVAL;
98 
99 	ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
100 					      buf, count);
101 
102 	if (ret) {
103 		hdd_err_rl("invalid input");
104 		return ret;
105 	}
106 
107 	sptr = buf_local;
108 	token = strsep(&sptr, " ");
109 	if (!token)
110 		return -EINVAL;
111 	if (kstrtou8(token, 0, &value))
112 		return -EINVAL;
113 
114 	hdd_debug("vdev_id: %d tx_delay_stats: %d",
115 		  adapter->deflink->vdev_id, value);
116 
117 	cdp_enable_disable_vdev_tx_delay_stats(dp_soc,
118 					       adapter->deflink->vdev_id,
119 					       value);
120 
121 	return count;
122 }
123 
124 static ssize_t
hdd_sysfs_dp_tx_delay_stats_store(struct device * dev,struct device_attribute * attr,char const * buf,size_t count)125 hdd_sysfs_dp_tx_delay_stats_store(struct device *dev,
126 				  struct device_attribute *attr,
127 				  char const *buf, size_t count)
128 {
129 	struct net_device *net_dev = container_of(dev, struct net_device, dev);
130 	struct osif_vdev_sync *vdev_sync;
131 	ssize_t errno_size;
132 
133 	errno_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
134 	if (errno_size)
135 		return errno_size;
136 
137 	errno_size = __hdd_sysfs_dp_tx_delay_stats_store(net_dev, buf, count);
138 
139 	osif_vdev_sync_op_stop(vdev_sync);
140 
141 	return errno_size;
142 }
143 
144 static DEVICE_ATTR(dp_tx_delay_stats, 0660,
145 		   hdd_sysfs_dp_tx_delay_stats_show,
146 		   hdd_sysfs_dp_tx_delay_stats_store);
147 
hdd_sysfs_dp_tx_delay_stats_create(struct hdd_adapter * adapter)148 int hdd_sysfs_dp_tx_delay_stats_create(struct hdd_adapter *adapter)
149 {
150 	int error;
151 
152 	error = device_create_file(&adapter->dev->dev,
153 				   &dev_attr_dp_tx_delay_stats);
154 	if (error)
155 		hdd_err("could not create dp_tx_delay_stats sysfs file");
156 
157 	return error;
158 }
159 
160 void
hdd_sysfs_dp_tx_delay_stats_destroy(struct hdd_adapter * adapter)161 hdd_sysfs_dp_tx_delay_stats_destroy(struct hdd_adapter *adapter)
162 {
163 	device_remove_file(&adapter->dev->dev, &dev_attr_dp_tx_delay_stats);
164 }
165