1 /*
2 * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /**
19 * DOC: wlan_hdd_sysfs_sta_bitrates.c
20 *
21 * implementation for creating sysfs file sta_bitrates and sap_bitrates
22 */
23
24 #include <wlan_hdd_includes.h>
25 #include <wlan_hdd_sysfs.h>
26 #include <wlan_hdd_sysfs_bitrates.h>
27 #include "osif_psoc_sync.h"
28 #include "osif_vdev_sync.h"
29 #include "sme_api.h"
30 #include "qc_sap_ioctl.h"
31 #include "wma_api.h"
32
wlan_hdd_sta_set_11n_rate(struct hdd_adapter * adapter,int rate_code)33 static int wlan_hdd_sta_set_11n_rate(struct hdd_adapter *adapter, int rate_code)
34 {
35 uint8_t preamble = 0, nss = 0, rix = 0;
36 int ret;
37 QDF_STATUS status;
38 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
39 enum wlan_phymode peer_phymode;
40 uint8_t *peer_mac = adapter->deflink->session.station.conn_info.bssid.bytes;
41
42 hdd_debug("Rate code %d", rate_code);
43
44 ret = wlan_hdd_validate_context(hdd_ctx);
45 if (ret)
46 return ret;
47
48 if (!wlan_hdd_validate_modules_state(hdd_ctx))
49 return -EINVAL;
50
51 if (rate_code != 0xffff) {
52 rix = RC_2_RATE_IDX(rate_code);
53 if (rate_code & 0x80) {
54 preamble = WMI_RATE_PREAMBLE_HT;
55 nss = HT_RC_2_STREAMS(rate_code) - 1;
56 } else {
57 status = ucfg_mlme_get_peer_phymode(hdd_ctx->psoc,
58 peer_mac,
59 &peer_phymode);
60 if (QDF_IS_STATUS_ERROR(status)) {
61 hdd_err("Failed to set rate");
62 return -EINVAL;
63 }
64 if (IS_WLAN_PHYMODE_HE(peer_phymode)) {
65 hdd_err("Do not set legacy rate %d in HE mode",
66 rate_code);
67 return -EINVAL;
68 }
69 nss = 0;
70 rix = RC_2_RATE_IDX(rate_code);
71 if (rate_code & 0x10) {
72 preamble = WMI_RATE_PREAMBLE_CCK;
73 if (rix != 0x3)
74 /* Enable Short preamble
75 * always for CCK except 1mbps
76 */
77 rix |= 0x4;
78 } else {
79 preamble = WMI_RATE_PREAMBLE_OFDM;
80 }
81 }
82 rate_code = hdd_assemble_rate_code(preamble, nss, rix);
83 }
84
85 hdd_debug("wmi_vdev_param_fixed_rate val %d rix %d preamble %x nss %d",
86 rate_code, rix, preamble, nss);
87
88 ret = wma_cli_set_command(adapter->deflink->vdev_id,
89 wmi_vdev_param_fixed_rate,
90 rate_code, VDEV_CMD);
91
92 return ret;
93 }
94
wlan_hdd_sta_set_vht_rate(struct hdd_adapter * adapter,int rate_code)95 static int wlan_hdd_sta_set_vht_rate(struct hdd_adapter *adapter, int rate_code)
96 {
97 uint8_t preamble = 0, nss = 0, rix = 0;
98 int ret;
99
100 hdd_debug("Rate code %d", rate_code);
101
102 if (rate_code != 0xffff) {
103 rix = RC_2_RATE_IDX_11AC(rate_code);
104 preamble = WMI_RATE_PREAMBLE_VHT;
105 nss = HT_RC_2_STREAMS_11AC(rate_code) - 1;
106 rate_code = hdd_assemble_rate_code(preamble, nss, rix);
107 }
108
109 hdd_debug("wmi_vdev_param_fixed_rate val %d rix %d preamble %x nss %d",
110 rate_code, rix, preamble, nss);
111
112 ret = wma_cli_set_command(adapter->deflink->vdev_id,
113 wmi_vdev_param_fixed_rate,
114 rate_code, VDEV_CMD);
115
116 return ret;
117 }
118
wlan_hdd_sta_set_11ax_rate(struct hdd_adapter * adapter,int rate)119 static int wlan_hdd_sta_set_11ax_rate(struct hdd_adapter *adapter, int rate)
120 {
121 return hdd_set_11ax_rate(adapter, rate, NULL);
122 }
123
wlan_hdd_sap_set_11n_rate(struct hdd_adapter * adapter,int rate_code)124 static int wlan_hdd_sap_set_11n_rate(struct hdd_adapter *adapter, int rate_code)
125 {
126 uint8_t preamble = 0, nss = 0, rix = 0;
127 struct sap_config *config = &adapter->deflink->session.ap.sap_config;
128 int ret;
129
130 hdd_debug("SET_HT_RATE val %d", rate_code);
131
132 if (rate_code != 0xff) {
133 rix = RC_2_RATE_IDX(rate_code);
134 if (rate_code & 0x80) {
135 if (config->SapHw_mode == eCSR_DOT11_MODE_11b ||
136 config->SapHw_mode == eCSR_DOT11_MODE_11b_ONLY ||
137 config->SapHw_mode == eCSR_DOT11_MODE_11g ||
138 config->SapHw_mode == eCSR_DOT11_MODE_11g_ONLY ||
139 config->SapHw_mode == eCSR_DOT11_MODE_abg ||
140 config->SapHw_mode == eCSR_DOT11_MODE_11a) {
141 hdd_err("Not valid mode for HT");
142 ret = -EIO;
143 return ret;
144 }
145 preamble = WMI_RATE_PREAMBLE_HT;
146 nss = HT_RC_2_STREAMS(rate_code) - 1;
147 } else if (rate_code & 0x10) {
148 if (config->SapHw_mode == eCSR_DOT11_MODE_11a) {
149 hdd_err("Not valid for cck");
150 ret = -EIO;
151 return ret;
152 }
153 preamble = WMI_RATE_PREAMBLE_CCK;
154 /* Enable Short preamble always for CCK except 1mbps */
155 if (rix != 0x3)
156 rix |= 0x4;
157 } else {
158 if (config->SapHw_mode == eCSR_DOT11_MODE_11b ||
159 config->SapHw_mode == eCSR_DOT11_MODE_11b_ONLY) {
160 hdd_err("Not valid for OFDM");
161 ret = -EIO;
162 return ret;
163 }
164 preamble = WMI_RATE_PREAMBLE_OFDM;
165 }
166 hdd_debug("SET_HT_RATE val %d rix %d preamble %x nss %d",
167 rate_code, rix, preamble, nss);
168 ret = wma_cli_set_command(adapter->deflink->vdev_id,
169 wmi_vdev_param_fixed_rate,
170 rate_code, VDEV_CMD);
171 return ret;
172 }
173
174 return -EINVAL;
175 }
176
wlan_hdd_sap_set_vht_rate(struct hdd_adapter * adapter,int rate_code)177 static int wlan_hdd_sap_set_vht_rate(struct hdd_adapter *adapter, int rate_code)
178 {
179 uint8_t preamble = 0, nss = 0, rix = 0;
180 int ret;
181 struct sap_config *config = &adapter->deflink->session.ap.sap_config;
182
183 if (config->SapHw_mode < eCSR_DOT11_MODE_11ac ||
184 config->SapHw_mode == eCSR_DOT11_MODE_11ax_ONLY ||
185 config->SapHw_mode == eCSR_DOT11_MODE_11be_ONLY) {
186 hdd_err("SET_VHT_RATE: SapHw_mode= 0x%x, ch_freq: %d",
187 config->SapHw_mode, config->chan_freq);
188 ret = -EIO;
189 return ret;
190 }
191
192 if (rate_code != 0xff) {
193 rix = RC_2_RATE_IDX_11AC(rate_code);
194 preamble = WMI_RATE_PREAMBLE_VHT;
195 nss = HT_RC_2_STREAMS_11AC(rate_code) - 1;
196
197 rate_code = hdd_assemble_rate_code(preamble, nss, rix);
198 }
199 hdd_debug("SET_VHT_RATE val %d rix %d preamble %x nss %d",
200 rate_code, rix, preamble, nss);
201
202 ret = wma_cli_set_command(adapter->deflink->vdev_id,
203 wmi_vdev_param_fixed_rate,
204 rate_code, VDEV_CMD);
205
206 return ret;
207 }
208
209 static int
wlan_hdd_sap_set_11ax_rate(struct hdd_adapter * adapter,int rate_code)210 wlan_hdd_sap_set_11ax_rate(struct hdd_adapter *adapter, int rate_code)
211 {
212 struct sap_config *config = &adapter->deflink->session.ap.sap_config;
213
214 return hdd_set_11ax_rate(adapter, rate_code, config);
215 }
216
217 static ssize_t
__hdd_sysfs_sta_bitrates_store(struct net_device * net_dev,char const * buf,size_t count)218 __hdd_sysfs_sta_bitrates_store(struct net_device *net_dev,
219 char const *buf, size_t count)
220 {
221 struct hdd_adapter *adapter = netdev_priv(net_dev);
222 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
223 struct hdd_context *hdd_ctx;
224 char *sptr, *token;
225 int ret, rate, rate_code;
226
227 if (hdd_validate_adapter(adapter))
228 return -EINVAL;
229
230 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
231 ret = wlan_hdd_validate_context(hdd_ctx);
232 if (ret)
233 return ret;
234
235 if (!wlan_hdd_validate_modules_state(hdd_ctx))
236 return -EINVAL;
237
238 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
239 buf, count);
240
241 if (ret) {
242 hdd_err_rl("invalid input");
243 return ret;
244 }
245
246 sptr = buf_local;
247 hdd_debug("sta_bitrates: count %zu buf_local:(%s)", count, buf_local);
248
249 /* Get rate_type */
250 token = strsep(&sptr, " ");
251 if (!token)
252 return -EINVAL;
253 if (kstrtoint(token, 0, &rate))
254 return -EINVAL;
255
256 /* Get rate */
257 token = strsep(&sptr, " ");
258 if (!token)
259 return -EINVAL;
260 if (kstrtoint(token, 0, &rate_code))
261 return -EINVAL;
262
263 switch (rate) {
264 case SET_11N_RATES:
265 ret = wlan_hdd_sta_set_11n_rate(adapter, rate_code);
266 if (ret) {
267 hdd_err_rl("failed to set 11n rates");
268 return ret;
269 }
270 break;
271 case SET_11AC_RATES:
272 ret = wlan_hdd_sta_set_vht_rate(adapter, rate_code);
273 if (ret) {
274 hdd_err_rl("failed to set 11ac rates");
275 return ret;
276 }
277 break;
278 case SET_11AX_RATES:
279 ret = wlan_hdd_sta_set_11ax_rate(adapter, rate_code);
280 if (ret) {
281 hdd_err_rl("failed to set 11ax rates");
282 return ret;
283 }
284 break;
285 default:
286 hdd_err("Invalid rate mode %u", rate);
287 return -EINVAL;
288 }
289
290 return count;
291 }
292
293 static ssize_t
__hdd_sysfs_sap_bitrates_store(struct net_device * net_dev,char const * buf,size_t count)294 __hdd_sysfs_sap_bitrates_store(struct net_device *net_dev,
295 char const *buf, size_t count)
296 {
297 struct hdd_adapter *adapter = netdev_priv(net_dev);
298 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
299 struct hdd_context *hdd_ctx;
300 char *sptr, *token;
301 int ret, rate, rate_code;
302
303 if (hdd_validate_adapter(adapter))
304 return -EINVAL;
305
306 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
307 ret = wlan_hdd_validate_context(hdd_ctx);
308 if (ret)
309 return ret;
310
311 if (!wlan_hdd_validate_modules_state(hdd_ctx))
312 return -EINVAL;
313
314 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
315 buf, count);
316
317 if (ret) {
318 hdd_err_rl("invalid input");
319 return ret;
320 }
321
322 sptr = buf_local;
323 hdd_debug("sta_bitrates: count %zu buf_local:(%s)", count, buf_local);
324
325 /* Get rate_type */
326 token = strsep(&sptr, " ");
327 if (!token)
328 return -EINVAL;
329 if (kstrtoint(token, 0, &rate))
330 return -EINVAL;
331
332 /* Get rate */
333 token = strsep(&sptr, " ");
334 if (!token)
335 return -EINVAL;
336 if (kstrtoint(token, 0, &rate_code))
337 return -EINVAL;
338
339 switch (rate) {
340 case SET_11N_RATES:
341 ret = wlan_hdd_sap_set_11n_rate(adapter, rate_code);
342 if (ret) {
343 hdd_err_rl("failed to set 11n rates");
344 return ret;
345 }
346 break;
347 case SET_11AC_RATES:
348 ret = wlan_hdd_sap_set_vht_rate(adapter, rate_code);
349 if (ret) {
350 hdd_err_rl("failed to set 11ac rates");
351 return ret;
352 }
353 break;
354 case SET_11AX_RATES:
355 ret = wlan_hdd_sap_set_11ax_rate(adapter, rate_code);
356 if (ret) {
357 hdd_err_rl("failed to set 11ax rates");
358 return ret;
359 }
360 break;
361 default:
362 hdd_err("Invalid rate mode %u", rate);
363 return -EINVAL;
364 }
365
366 return count;
367 }
368
369 static ssize_t
hdd_sysfs_sap_bitrates_store(struct device * dev,struct device_attribute * attr,char const * buf,size_t count)370 hdd_sysfs_sap_bitrates_store(struct device *dev,
371 struct device_attribute *attr,
372 char const *buf, size_t count)
373 {
374 struct net_device *net_dev = container_of(dev, struct net_device, dev);
375 struct osif_vdev_sync *vdev_sync;
376 ssize_t err_size;
377
378 err_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
379 if (err_size)
380 return err_size;
381
382 err_size = __hdd_sysfs_sap_bitrates_store(net_dev, buf, count);
383
384 osif_vdev_sync_op_stop(vdev_sync);
385
386 return err_size;
387 }
388
389 static ssize_t
hdd_sysfs_sta_bitrates_store(struct device * dev,struct device_attribute * attr,char const * buf,size_t count)390 hdd_sysfs_sta_bitrates_store(struct device *dev,
391 struct device_attribute *attr,
392 char const *buf, size_t count)
393 {
394 struct net_device *net_dev = container_of(dev, struct net_device, dev);
395 struct osif_vdev_sync *vdev_sync;
396 ssize_t err_size;
397
398 err_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
399 if (err_size)
400 return err_size;
401
402 err_size = __hdd_sysfs_sta_bitrates_store(net_dev, buf, count);
403
404 osif_vdev_sync_op_stop(vdev_sync);
405
406 return err_size;
407 }
408
409 static DEVICE_ATTR(sta_bitrates, 0220,
410 NULL, hdd_sysfs_sta_bitrates_store);
411
412 static DEVICE_ATTR(sap_bitrates, 0220,
413 NULL, hdd_sysfs_sap_bitrates_store);
414
hdd_sysfs_sta_bitrates_create(struct hdd_adapter * adapter)415 int hdd_sysfs_sta_bitrates_create(struct hdd_adapter *adapter)
416 {
417 int error;
418
419 error = device_create_file(&adapter->dev->dev,
420 &dev_attr_sta_bitrates);
421 if (error)
422 hdd_err("could not create sta_bitrates sysfs file");
423
424 return error;
425 }
426
hdd_sysfs_sap_bitrates_create(struct hdd_adapter * adapter)427 int hdd_sysfs_sap_bitrates_create(struct hdd_adapter *adapter)
428 {
429 int error;
430
431 error = device_create_file(&adapter->dev->dev,
432 &dev_attr_sap_bitrates);
433 if (error)
434 hdd_err("could not create sap_bitrates sysfs file");
435
436 return error;
437 }
hdd_sysfs_sta_bitrates_destroy(struct hdd_adapter * adapter)438 void hdd_sysfs_sta_bitrates_destroy(struct hdd_adapter *adapter)
439 {
440 device_remove_file(&adapter->dev->dev, &dev_attr_sta_bitrates);
441 }
442
hdd_sysfs_sap_bitrates_destroy(struct hdd_adapter * adapter)443 void hdd_sysfs_sap_bitrates_destroy(struct hdd_adapter *adapter)
444 {
445 device_remove_file(&adapter->dev->dev, &dev_attr_sap_bitrates);
446 }
447