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