1 /*
2 * Copyright (c) 2022 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_add_timestamp.c
19 *
20 * Implementation for creating sysfs files:
21 *
22 * dp_pkt_add_ts
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_add_timestamp.h>
29 #include "qdf_trace.h"
30
31 #define MAX_USER_COMMAND_SIZE_TIMESTAMP 512
32
hdd_set_dp_pkt_add_ts_info(char * in_str)33 static int hdd_set_dp_pkt_add_ts_info(char *in_str)
34 {
35 char *str, *token, *substr, *subtoken;
36 enum qdf_pkt_supported_proto proto;
37 uint16_t port, offset;
38 int ret;
39
40 str = in_str;
41 while (1) {
42 token = strsep(&str, ",");
43 if (!token)
44 break;
45
46 substr = token;
47
48 /* get protocol */
49 subtoken = strsep(&substr, ":");
50 if (!subtoken)
51 return -EINVAL;
52
53 if (strncmp(subtoken, "TCP", 3) == 0) {
54 proto = QDF_PKT_PROTO_TCP;
55 } else if (strncmp(subtoken, "UDP", 3) == 0) {
56 proto = QDF_PKT_PROTO_UDP;
57 } else {
58 hdd_err("protocol not supported");
59 return -EINVAL;
60 }
61
62 /* get destination port value */
63 subtoken = strsep(&substr, ":");
64 if (!subtoken)
65 return -EINVAL;
66
67 ret = kstrtou16(subtoken, 0, &port);
68 if (ret) {
69 hdd_err("Invalid port value ret %d", ret);
70 return -EINVAL;
71 }
72
73 if (port < 1 || port > 65535) {
74 hdd_err("port not valid");
75 return -EINVAL;
76 }
77
78 /* get offset */
79 subtoken = strsep(&substr, ":");
80 if (!subtoken)
81 return -EINVAL;
82
83 ret = kstrtou16(subtoken, 0, &offset);
84 if (ret) {
85 hdd_err("Invalid offset value ret %d", ret);
86 return -EINVAL;
87 }
88
89 ret = qdf_set_dp_pkt_add_ts_info(proto, port, offset);
90 if (ret) {
91 hdd_err("pkt info set failed");
92 return -EINVAL;
93 }
94 }
95 return 0;
96 }
97
98 static ssize_t
__hdd_sysfs_dp_pkt_add_ts_store(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,char const * buf,size_t count)99 __hdd_sysfs_dp_pkt_add_ts_store(struct hdd_context *hdd_ctx,
100 struct kobj_attribute *attr,
101 char const *buf, size_t count)
102 {
103 char buf_local[MAX_USER_COMMAND_SIZE_TIMESTAMP + 1];
104 char *str;
105 int ret;
106
107 if (!wlan_hdd_validate_modules_state(hdd_ctx))
108 return -EINVAL;
109
110 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
111 buf, count);
112 if (ret) {
113 hdd_err_rl("invalid input");
114 return ret;
115 }
116
117 str = skip_spaces(buf_local);
118 if (strlen(str) == 0) {
119 qdf_clear_dp_pkt_add_ts_info();
120 return count;
121 }
122
123 qdf_clear_dp_pkt_add_ts_info();
124 ret = hdd_set_dp_pkt_add_ts_info(str);
125 if (ret)
126 hdd_err("all protocol do not set successfully");
127 return count;
128 }
129
hdd_sysfs_dp_pkt_add_ts_store(struct kobject * kobj,struct kobj_attribute * attr,char const * buf,size_t count)130 static ssize_t hdd_sysfs_dp_pkt_add_ts_store(struct kobject *kobj,
131 struct kobj_attribute *attr,
132 char const *buf, size_t count)
133 {
134 struct osif_psoc_sync *psoc_sync;
135 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
136 ssize_t errno_size;
137 int ret;
138
139 ret = wlan_hdd_validate_context(hdd_ctx);
140 if (ret != 0)
141 return ret;
142
143 errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
144 &psoc_sync);
145 if (errno_size)
146 return errno_size;
147
148 errno_size = __hdd_sysfs_dp_pkt_add_ts_store(hdd_ctx, attr,
149 buf, count);
150
151 osif_psoc_sync_op_stop(psoc_sync);
152
153 return errno_size;
154 }
155
156 static ssize_t
__hdd_sysfs_dp_pkt_add_ts_show(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,char * buf)157 __hdd_sysfs_dp_pkt_add_ts_show(struct hdd_context *hdd_ctx,
158 struct kobj_attribute *attr, char *buf)
159 {
160 if (!wlan_hdd_validate_modules_state(hdd_ctx))
161 return -EINVAL;
162
163 return qdf_show_dp_pkt_add_ts_info(buf, PAGE_SIZE);
164 }
165
hdd_sysfs_dp_pkt_add_ts_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)166 static ssize_t hdd_sysfs_dp_pkt_add_ts_show(struct kobject *kobj,
167 struct kobj_attribute *attr,
168 char *buf)
169 {
170 struct osif_psoc_sync *psoc_sync;
171 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
172 ssize_t errno_size;
173 int ret;
174
175 ret = wlan_hdd_validate_context(hdd_ctx);
176 if (ret != 0)
177 return ret;
178
179 errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
180 &psoc_sync);
181 if (errno_size)
182 return errno_size;
183
184 errno_size = __hdd_sysfs_dp_pkt_add_ts_show(hdd_ctx, attr, buf);
185
186 osif_psoc_sync_op_stop(psoc_sync);
187
188 return errno_size;
189 }
190
191 static struct kobj_attribute dp_pkt_add_ts_attribute =
192 __ATTR(dp_pkt_add_ts, 0660, hdd_sysfs_dp_pkt_add_ts_show,
193 hdd_sysfs_dp_pkt_add_ts_store);
194
hdd_sysfs_dp_pkt_add_ts_create(struct kobject * driver_kobject)195 int hdd_sysfs_dp_pkt_add_ts_create(struct kobject *driver_kobject)
196 {
197 int error;
198
199 if (!driver_kobject) {
200 hdd_err("could not get driver kobject!");
201 return -EINVAL;
202 }
203
204 error = sysfs_create_file(driver_kobject,
205 &dp_pkt_add_ts_attribute.attr);
206 if (error)
207 hdd_err("could not create dp_pkt_add_ts sysfs file");
208
209 return error;
210 }
211
212 void
hdd_sysfs_dp_pkt_add_ts_destroy(struct kobject * driver_kobject)213 hdd_sysfs_dp_pkt_add_ts_destroy(struct kobject *driver_kobject)
214 {
215 if (!driver_kobject) {
216 hdd_err("could not get driver kobject!");
217 return;
218 }
219 sysfs_remove_file(driver_kobject, &dp_pkt_add_ts_attribute.attr);
220 }
221