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_traffic_end_indication.c
19 *
20 * implementation for creating sysfs files:
21 *
22 * dp_traffic_end_indication
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_traffic_end_indication.h>
29 #include <wlan_dp_ucfg_api.h>
30
31 static ssize_t
__hdd_sysfs_dp_traffic_end_indication_show(struct net_device * net_dev,char * buf)32 __hdd_sysfs_dp_traffic_end_indication_show(struct net_device *net_dev,
33 char *buf)
34 {
35 struct hdd_adapter *adapter = netdev_priv(net_dev);
36 struct wlan_objmgr_vdev *vdev;
37 struct dp_traffic_end_indication info = {0};
38 QDF_STATUS status;
39 int ret;
40
41 if (hdd_validate_adapter(adapter))
42 return -EINVAL;
43
44 ret = wlan_hdd_validate_context(adapter->hdd_ctx);
45 if (ret)
46 return ret;
47
48 if (!wlan_hdd_validate_modules_state(adapter->hdd_ctx))
49 return -EINVAL;
50
51 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
52 if (!vdev)
53 return -EINVAL;
54
55 status = ucfg_dp_traffic_end_indication_get(vdev, &info);
56 hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
57
58 if (!QDF_IS_STATUS_SUCCESS(status))
59 return -EINVAL;
60
61 hdd_debug("vdev_id:%u traffic end indication:%u defdscp:%u spldscp:%u",
62 adapter->deflink->vdev_id, info.enabled,
63 info.def_dscp, info.spl_dscp);
64
65 ret = scnprintf(buf, PAGE_SIZE, "%u %u %u\n",
66 info.enabled, info.def_dscp, info.def_dscp);
67 return ret;
68 }
69
70 static ssize_t
hdd_sysfs_dp_traffic_end_indication_show(struct device * dev,struct device_attribute * attr,char * buf)71 hdd_sysfs_dp_traffic_end_indication_show(struct device *dev,
72 struct device_attribute *attr,
73 char *buf)
74 {
75 struct net_device *net_dev = container_of(dev, struct net_device, dev);
76 struct osif_vdev_sync *vdev_sync;
77 ssize_t err_size;
78
79 err_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
80 if (err_size)
81 return err_size;
82
83 err_size = __hdd_sysfs_dp_traffic_end_indication_show(net_dev, buf);
84
85 osif_vdev_sync_op_stop(vdev_sync);
86
87 return err_size;
88 }
89
90 static ssize_t
__hdd_sysfs_dp_traffic_end_indication_store(struct net_device * net_dev,const char * buf,size_t count)91 __hdd_sysfs_dp_traffic_end_indication_store(struct net_device *net_dev,
92 const char *buf,
93 size_t count)
94 {
95 struct hdd_adapter *adapter = netdev_priv(net_dev);
96 struct dp_traffic_end_indication info = {0};
97 struct wlan_objmgr_vdev *vdev;
98 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
99 char *sptr, *token;
100 uint8_t value, defdscp, spldscp;
101 int ret;
102
103 if (hdd_validate_adapter(adapter))
104 return -EINVAL;
105
106 ret = wlan_hdd_validate_context(adapter->hdd_ctx);
107 if (ret)
108 return ret;
109
110 if (!wlan_hdd_validate_modules_state(adapter->hdd_ctx))
111 return -EINVAL;
112
113 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
114 buf, count);
115 if (ret) {
116 hdd_err("invalid input");
117 return ret;
118 }
119
120 sptr = buf_local;
121 /* Enable/disable traffic end indication*/
122 token = strsep(&sptr, " ");
123 if (!token)
124 return -EINVAL;
125 if (kstrtou8(token, 0, &value))
126 return -EINVAL;
127
128 /* Default DSCP Value */
129 token = strsep(&sptr, " ");
130 if (!token)
131 return -EINVAL;
132 if (kstrtou8(token, 0, &defdscp))
133 return -EINVAL;
134
135 /* Special DSCP Value */
136 token = strsep(&sptr, " ");
137 if (!token)
138 return -EINVAL;
139 if (kstrtou8(token, 0, &spldscp))
140 return -EINVAL;
141
142 if ((defdscp > 63) || (spldscp > 63)) {
143 hdd_err("invalid dscp value");
144 return -EINVAL;
145 }
146
147 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
148 if (!vdev)
149 return -EINVAL;
150
151 info.enabled = !!value;
152 adapter->traffic_end_ind_en = info.enabled;
153 if (info.enabled) {
154 info.def_dscp = defdscp;
155 info.spl_dscp = spldscp;
156 } else {
157 info.def_dscp = 0;
158 info.spl_dscp = 0;
159 }
160
161 hdd_debug("vdev_id:%u traffic end indication:%u defdscp:%u spldscp:%u",
162 adapter->deflink->vdev_id, value, defdscp, spldscp);
163
164 ucfg_dp_traffic_end_indication_set(vdev, info);
165 wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID);
166
167 return count;
168 }
169
170 static ssize_t
hdd_sysfs_dp_traffic_end_indication_store(struct device * dev,struct device_attribute * attr,char const * buf,size_t count)171 hdd_sysfs_dp_traffic_end_indication_store(struct device *dev,
172 struct device_attribute *attr,
173 char const *buf, size_t count)
174 {
175 struct net_device *net_dev = container_of(dev, struct net_device, dev);
176 struct osif_vdev_sync *vdev_sync;
177 ssize_t errno_size;
178
179 errno_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
180 if (errno_size)
181 return errno_size;
182
183 errno_size = __hdd_sysfs_dp_traffic_end_indication_store(net_dev,
184 buf, count);
185
186 osif_vdev_sync_op_stop(vdev_sync);
187
188 return errno_size;
189 }
190
191 static DEVICE_ATTR(dp_traffic_end_indication, 0660,
192 hdd_sysfs_dp_traffic_end_indication_show,
193 hdd_sysfs_dp_traffic_end_indication_store);
194
hdd_sysfs_dp_traffic_end_indication_create(struct hdd_adapter * adapter)195 int hdd_sysfs_dp_traffic_end_indication_create(struct hdd_adapter *adapter)
196 {
197 int error;
198
199 error = device_create_file(&adapter->dev->dev,
200 &dev_attr_dp_traffic_end_indication);
201 if (error)
202 hdd_err("could not create traffic_end_indication sysfs file");
203
204 return error;
205 }
206
207 void
hdd_sysfs_dp_traffic_end_indication_destroy(struct hdd_adapter * adapter)208 hdd_sysfs_dp_traffic_end_indication_destroy(struct hdd_adapter *adapter)
209 {
210 device_remove_file(&adapter->dev->dev,
211 &dev_attr_dp_traffic_end_indication);
212 }
213