[RAMEN9610-20095][lv] host update 10.5.1.1 for lenovo only
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / drivers / net / wireless / scsc / ioctl.c
CommitLineData
4dcd9de9
TK
1/****************************************************************************
2 *
3 * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved
4 *
5 ****************************************************************************/
6
7#include "ioctl.h"
8#include "debug.h"
9#include "mlme.h"
10#include "mgt.h"
11#include "cac.h"
12#include "hip.h"
13#include "netif.h"
14#include <net/netlink.h>
15#include <linux/netdevice.h>
16#include <linux/ieee80211.h>
17#include "mib.h"
18#include <scsc/scsc_mx.h>
19#include <scsc/scsc_log_collector.h>
20#include "dev.h"
21#include "fapi.h"
22
23#define CMD_RXFILTERADD "RXFILTER-ADD"
24#define CMD_RXFILTERREMOVE "RXFILTER-REMOVE"
25#define CMD_RXFILTERSTART "RXFILTER-START"
26#define CMD_RXFILTERSTOP "RXFILTER-STOP"
27#define CMD_SETCOUNTRYREV "SETCOUNTRYREV"
28#define CMD_GETCOUNTRYREV "GETCOUNTRYREV"
29#define CMD_SETROAMTRIGGER "SETROAMTRIGGER"
30#define CMD_GETROAMTRIGGER "GETROAMTRIGGER"
31#define CMD_SETSUSPENDMODE "SETSUSPENDMODE"
32#define CMD_SETROAMDELTA "SETROAMDELTA"
33#define CMD_GETROAMDELTA "GETROAMDELTA"
34#define CMD_SETROAMSCANPERIOD "SETROAMSCANPERIOD"
35#define CMD_GETROAMSCANPERIOD "GETROAMSCANPERIOD"
36#define CMD_SETFULLROAMSCANPERIOD "SETFULLROAMSCANPERIOD"
37#define CMD_GETFULLROAMSCANPERIOD "GETFULLROAMSCANPERIOD"
38#define CMD_SETSCANCHANNELTIME "SETSCANCHANNELTIME"
39#define CMD_GETSCANCHANNELTIME "GETSCANCHANNELTIME"
40#define CMD_SETSCANNPROBES "SETSCANNPROBES"
41#define CMD_GETSCANNPROBES "GETSCANNPROBES"
42#define CMD_SETROAMMODE "SETROAMMODE"
43#define CMD_GETROAMMODE "GETROAMMODE"
44#define CMD_SETROAMINTRABAND "SETROAMINTRABAND"
45#define CMD_GETROAMINTRABAND "GETROAMINTRABAND"
46#define CMD_SETROAMBAND "SETROAMBAND"
47#define CMD_GETROAMBAND "GETROAMBAND"
48#define CMD_SETROAMSCANCONTROL "SETROAMSCANCONTROL"
49#define CMD_GETROAMSCANCONTROL "GETROAMSCANCONTROL"
50#define CMD_SETSCANHOMETIME "SETSCANHOMETIME"
51#define CMD_GETSCANHOMETIME "GETSCANHOMETIME"
52#define CMD_SETSCANHOMEAWAYTIME "SETSCANHOMEAWAYTIME"
53#define CMD_GETSCANHOMEAWAYTIME "GETSCANHOMEAWAYTIME"
54#define CMD_SETOKCMODE "SETOKCMODE"
55#define CMD_GETOKCMODE "GETOKCMODE"
56#define CMD_SETWESMODE "SETWESMODE"
57#define CMD_GETWESMODE "GETWESMODE"
58#define CMD_SET_PMK "SET_PMK"
59#define CMD_HAPD_GET_CHANNEL "HAPD_GET_CHANNEL"
60#define CMD_SET_SAP_CHANNEL_LIST "SET_SAP_CHANNEL_LIST"
61#define CMD_REASSOC "REASSOC"
62#define CMD_SETROAMSCANCHANNELS "SETROAMSCANCHANNELS"
63#define CMD_GETROAMSCANCHANNELS "GETROAMSCANCHANNELS"
64#define CMD_SENDACTIONFRAME "SENDACTIONFRAME"
65#define CMD_HAPD_MAX_NUM_STA "HAPD_MAX_NUM_STA"
66#define CMD_COUNTRY "COUNTRY"
67#define CMD_SEND_GK "SEND_GK"
68#define CMD_SETAPP2PWPSIE "SET_AP_P2P_WPS_IE"
69#define CMD_P2PSETPS "P2P_SET_PS"
70#define CMD_P2PSETNOA "P2P_SET_NOA"
71#define CMD_P2PECSA "P2P_ECSA"
72#define CMD_P2PLOSTART "P2P_LO_START"
73#define CMD_P2PLOSTOP "P2P_LO_STOP"
74#define CMD_TDLSCHANNELSWITCH "TDLS_CHANNEL_SWITCH"
75#define CMD_SETROAMOFFLOAD "SETROAMOFFLOAD"
76#define CMD_SETROAMOFFLAPLIST "SETROAMOFFLAPLIST"
77#ifdef CONFIG_SCSC_WLAN_LOW_LATENCY_MODE
78#define CMD_SET_LATENCY_MODE "SET_LATENCY_MODE"
79#define CMD_SET_POWER_MGMT "SET_POWER_MGMT"
80#endif
81#define CMD_SET_DISCONNECT_IES "SET_DISCONNECT_IES"
82
83#define CMD_SETBAND "SETBAND"
84#define CMD_GETBAND "GETBAND"
85#define CMD_SET_FCC_CHANNEL "SET_FCC_CHANNEL"
86
87#define CMD_FAKEMAC "FAKEMAC"
88
89#define CMD_GETBSSRSSI "GET_BSS_RSSI"
90#define CMD_GETBSSINFO "GETBSSINFO"
91#define CMD_GETSTAINFO "GETSTAINFO"
92#define CMD_GETASSOCREJECTINFO "GETASSOCREJECTINFO"
93
94#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON
95#define CMD_BEACON_RECV "BEACON_RECV"
96#endif
97#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
98#define CMD_SET_ENHANCED_ARP_TARGET "SET_ENHANCED_ARP_TARGET"
99#define CMD_GET_ENHANCED_ARP_COUNTS "GET_ENHANCED_ARP_COUNTS"
100#endif
101
102/* Known commands from framework for which no handlers */
103#define CMD_AMPDU_MPDU "AMPDU_MPDU"
104#define CMD_BTCOEXMODE "BTCOEXMODE"
105#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START"
106#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP"
107#define CMD_CHANGE_RL "CHANGE_RL"
108#define CMD_INTERFACE_CREATE "INTERFACE_CREATE"
109#define CMD_INTERFACE_DELETE "INTERFACE_DELETE"
110#define CMD_SET_INDOOR_CHANNELS "SET_INDOOR_CHANNELS"
111#define CMD_GET_INDOOR_CHANNELS "GET_INDOOR_CHANNELS"
112#define CMD_LTECOEX "LTECOEX"
113#define CMD_MIRACAST "MIRACAST"
114#define CMD_RESTORE_RL "RESTORE_RL"
115#define CMD_RPSMODE "RPSMODE"
116#define CMD_SETCCXMODE "SETCCXMODE"
117#define CMD_SETDFSSCANMODE "SETDFSSCANMODE"
118#define CMD_SETJOINPREFER "SETJOINPREFER"
119#define CMD_SETSINGLEANT "SETSINGLEANT"
120#define CMD_SET_TX_POWER_CALLING "SET_TX_POWER_CALLING"
121
122#define CMD_DRIVERDEBUGDUMP "DEBUG_DUMP"
123#define CMD_DRIVERDEBUGCOMMAND "DEBUG_COMMAND"
124#define CMD_TESTFORCEHANG "SLSI_TEST_FORCE_HANG"
125#define CMD_GETREGULATORY "GETREGULATORY"
126
127#define CMD_SET_TX_POWER_SAR "SET_TX_POWER_SAR"
128#define CMD_GET_TX_POWER_SAR "GET_TX_POWER_SAR"
129
130#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
131#define CMD_ENHANCED_PKT_FILTER "ENHANCED_PKT_FILTER"
132#endif
1f642a2e
Y
133#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
134#define CMD_ABNORMAL_MULTICAST_PKT_FILTER "ABNORMAL_MULTICAST_PKT_FILTER"
135#endif
4dcd9de9
TK
136#define CMD_GET_MAX_LINK_SPEED "GET_MAX_LINK_SPEED"
137
138#ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS
139#define CMD_SET_NUM_ANTENNAS "SET_NUM_ANTENNAS"
140#endif
141
142#define ROAMOFFLAPLIST_MIN 1
143#define ROAMOFFLAPLIST_MAX 100
144
145static int slsi_parse_hex(unsigned char c)
146{
147 if (c >= '0' && c <= '9')
148 return c - '0';
149 if (c >= 'a' && c <= 'f')
150 return c - 'a' + 10;
151 if (c >= 'A' && c <= 'F')
152 return c - 'A' + 10;
153 return 0;
154}
155
156static void slsi_machexstring_to_macarray(char *mac_str, u8 *mac_arr)
157{
158 mac_arr[0] = slsi_parse_hex(mac_str[0]) << 4 | slsi_parse_hex(mac_str[1]);
159 mac_arr[1] = slsi_parse_hex(mac_str[3]) << 4 | slsi_parse_hex(mac_str[4]);
160 mac_arr[2] = slsi_parse_hex(mac_str[6]) << 4 | slsi_parse_hex(mac_str[7]);
161 mac_arr[3] = slsi_parse_hex(mac_str[9]) << 4 | slsi_parse_hex(mac_str[10]);
162 mac_arr[4] = slsi_parse_hex(mac_str[12]) << 4 | slsi_parse_hex(mac_str[13]);
163 mac_arr[5] = slsi_parse_hex(mac_str[15]) << 4 | slsi_parse_hex(mac_str[16]);
164}
165
166static ssize_t slsi_set_suspend_mode(struct net_device *dev, char *command)
167{
168 int vif;
169 struct netdev_vif *netdev_vif = netdev_priv(dev);
170 struct slsi_dev *sdev = netdev_vif->sdev;
171 int user_suspend_mode;
172 int previous_suspend_mode;
173 u8 host_state;
174 int ret = 0;
175
176 user_suspend_mode = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0';
177
178 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
179 previous_suspend_mode = sdev->device_config.user_suspend_mode;
180 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
181
182 if (user_suspend_mode != previous_suspend_mode) {
183 SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex);
184 for (vif = 1; vif <= CONFIG_SCSC_WLAN_MAX_INTERFACES; vif++) {
185 struct net_device *dev = slsi_get_netdev_locked(sdev, vif);
186 struct netdev_vif *ndev_vif;
187
188 if (!dev)
189 continue;
190
191 ndev_vif = netdev_priv(dev);
192 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
193 if ((ndev_vif->activated) &&
194 (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) &&
195 (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) {
196 if (user_suspend_mode)
197 ret = slsi_update_packet_filters(sdev, dev);
198 else
199 ret = slsi_clear_packet_filters(sdev, dev);
200 if (ret != 0)
201 SLSI_NET_ERR(dev, "Error in updating /clearing the packet filters,ret=%d", ret);
202 }
203
204 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
205 }
206 SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
207 }
208
209 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
210 sdev->device_config.user_suspend_mode = user_suspend_mode;
211 host_state = sdev->device_config.host_state;
212
213 if (!sdev->device_config.user_suspend_mode)
214 host_state = host_state | SLSI_HOSTSTATE_LCD_ACTIVE;
215 else
216 host_state = host_state & ~SLSI_HOSTSTATE_LCD_ACTIVE;
217 sdev->device_config.host_state = host_state;
218
219 ret = slsi_mlme_set_host_state(sdev, dev, host_state);
220 if (ret != 0)
221 SLSI_NET_ERR(dev, "Error in setting the Host State, ret=%d", ret);
222
223 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
224 return ret;
225}
226
227static ssize_t slsi_set_p2p_oppps(struct net_device *dev, char *command, int buf_len)
228{
229 struct netdev_vif *ndev_vif;
230 struct slsi_dev *sdev;
231 u8 *p2p_oppps_param = NULL;
232 int offset = 0;
233 unsigned int ct_param;
234 unsigned int legacy_ps;
235 unsigned int opp_ps;
236 int readbyte = 0;
237 int result = 0;
238
239 p2p_oppps_param = command + strlen(CMD_P2PSETPS) + 1;
240 ndev_vif = netdev_priv(dev);
241 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
242
243 /* The NOA param shall be added only after P2P-VIF is active */
244 if ((!ndev_vif->activated) || (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO)) {
245 SLSI_ERR_NODEV("P2P GO vif not activated\n");
246 result = -EINVAL;
247 goto exit;
248 }
249
250 sdev = ndev_vif->sdev;
251 readbyte = slsi_str_to_int(&p2p_oppps_param[offset], &legacy_ps);
252 if (!readbyte) {
253 SLSI_ERR(sdev, "ct_param: failed to read legacy_ps\n");
254 result = -EINVAL;
255 goto exit;
256 }
257 offset = offset + readbyte + 1;
258
259 readbyte = slsi_str_to_int(&p2p_oppps_param[offset], &opp_ps);
260 if (!readbyte) {
261 SLSI_ERR(sdev, "ct_param: failed to read ct_param\n");
262 result = -EINVAL;
263 goto exit;
264 }
265 offset = offset + readbyte + 1;
266
267 readbyte = slsi_str_to_int(&p2p_oppps_param[offset], &ct_param);
268 if (!readbyte) {
269 SLSI_ERR(sdev, "ct_param: failed to read ct_param\n");
270 result = -EINVAL;
271 goto exit;
272 }
273
274 if (opp_ps == 0)
275 result = slsi_mlme_set_ctwindow(sdev, dev, opp_ps);
276 else if (ct_param < (unsigned int)ndev_vif->ap.beacon_interval)
277 result = slsi_mlme_set_ctwindow(sdev, dev, ct_param);
278 else
279 SLSI_DBG1(sdev, SLSI_CFG80211, "p2p ct window = %d is out of range for beacon interval(%d)\n", ct_param, ndev_vif->ap.beacon_interval);
280exit:
281 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
282
283 return result;
284}
285
286static ssize_t slsi_p2p_set_noa_params(struct net_device *dev, char *command, int buf_len)
287{
288 struct netdev_vif *ndev_vif;
289 struct slsi_dev *sdev;
290 int result = 0;
291 u8 *noa_params = NULL;
292 int offset = 0;
293 int readbyte = 0;
294 unsigned int noa_count;
295 unsigned int duration;
296 unsigned int interval;
297
298 noa_params = command + strlen(CMD_P2PSETNOA) + 1;
299 ndev_vif = netdev_priv(dev);
300 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
301 /* The NOA param shall be added only after P2P-VIF is active */
302 if ((!ndev_vif->activated) || (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO)) {
303 SLSI_ERR_NODEV("P2P GO vif not activated\n");
304 result = -EINVAL;
305 goto exit;
306 }
307
308 sdev = ndev_vif->sdev;
309 readbyte = slsi_str_to_int(&noa_params[offset], &noa_count);
310 if (!readbyte) {
311 SLSI_ERR(sdev, "noa_count: failed to read a numeric value\n");
312 result = -EINVAL;
313 goto exit;
314 }
315 offset = offset + readbyte + 1;
316
317 readbyte = slsi_str_to_int(&noa_params[offset], &interval);
318 if (!readbyte) {
319 SLSI_ERR(sdev, "interval: failed to read a numeric value\n");
320 result = -EINVAL;
321 goto exit;
322 }
323 offset = offset + readbyte + 1;
324
325 readbyte = slsi_str_to_int(&noa_params[offset], &duration);
326 if (!readbyte) {
327 SLSI_ERR(sdev, "duration: failed to read a numeric value, at offset(%d)\n", offset);
328 result = -EINVAL;
329 goto exit;
330 }
331
332 /* Skip start time */
333 result = slsi_mlme_set_p2p_noa(sdev, dev, noa_count, interval, duration);
334
335exit:
336 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
337 return result;
338}
339
340static ssize_t slsi_p2p_ecsa(struct net_device *dev, char *command)
341{
342 struct netdev_vif *ndev_vif;
343 struct netdev_vif *group_dev_vif;
344 struct slsi_dev *sdev;
345 struct net_device *group_dev = NULL;
346 int result = 0;
347 u8 *ecsa_params = NULL;
348 int offset = 0;
349 int readbyte = 0;
350 unsigned int channel;
351 unsigned int bandwidth;
352 u16 center_freq = 0;
353 u16 chan_info = 0;
354 struct cfg80211_chan_def chandef;
355 enum nl80211_band band;
356 enum nl80211_channel_type chan_type = NL80211_CHAN_NO_HT;
357
358 ecsa_params = command + strlen(CMD_P2PECSA) + 1;
359 ndev_vif = netdev_priv(dev);
360 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
361 sdev = ndev_vif->sdev;
362 group_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN);
363 if (!group_dev) {
364 SLSI_INFO(sdev, "No Group net_dev found\n");
365 return -EINVAL;
366 }
367 readbyte = slsi_str_to_int(&ecsa_params[offset], &channel);
368 if (!readbyte) {
369 SLSI_ERR(sdev, "channel: failed to read a numeric value\n");
370 result = -EINVAL;
371 goto exit;
372 }
373 offset = offset + readbyte + 1;
374 readbyte = slsi_str_to_int(&ecsa_params[offset], &bandwidth);
375 if (!readbyte) {
376 SLSI_ERR(sdev, "bandwidth: failed to read a numeric value\n");
377 result = -EINVAL;
378 goto exit;
379 }
380 offset = offset + readbyte + 1;
381 band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
382 center_freq = ieee80211_channel_to_frequency(channel, band);
383 SLSI_DBG1(sdev, SLSI_CFG80211, "p2p ecsa_params (center_freq)= (%d)\n", center_freq);
384 chandef.chan = ieee80211_get_channel(sdev->wiphy, center_freq);
385 chandef.width = (band == NL80211_BAND_2GHZ) ? NL80211_CHAN_WIDTH_20_NOHT : NL80211_CHAN_WIDTH_80;
386
387#ifndef SSB_4963_FIXED
388 /* Default HT40 configuration */
389 if (sdev->band_5g_supported) {
390 if (bandwidth == 80) {
391 chandef.width = NL80211_CHAN_WIDTH_40;
392 bandwidth = 40;
393 if (channel == 36 || channel == 44 || channel == 149 || channel == 157)
394 chan_type = NL80211_CHAN_HT40PLUS;
395 else
396 chan_type = NL80211_CHAN_HT40MINUS;
397 }
398 }
399#endif
400 if (channel == 165 && bandwidth != 20) {
401 bandwidth = 20;
402 chan_type = NL80211_CHAN_HT20;
403 }
404 cfg80211_chandef_create(&chandef, chandef.chan, chan_type);
405 chan_info = slsi_get_chann_info(sdev, &chandef);
406 if (bandwidth != 20)
407 center_freq = slsi_get_center_freq1(sdev, chan_info, center_freq);
408 group_dev_vif = netdev_priv(group_dev);
409 SLSI_MUTEX_LOCK(group_dev_vif->vif_mutex);
410 result = slsi_mlme_channel_switch(sdev, group_dev, center_freq, chan_info);
411 SLSI_MUTEX_UNLOCK(group_dev_vif->vif_mutex);
412
413exit:
414 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
415 return result;
416}
417
418static ssize_t slsi_ap_vendor_ies_write(struct slsi_dev *sdev, struct net_device *dev, u8 *ie,
419 size_t ie_len, u16 purpose)
420{
421 u8 *vendor_ie = NULL;
422 int result = 0;
423 struct netdev_vif *ndev_vif;
424
425 ndev_vif = netdev_priv(dev);
426 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
427 /* During AP start before mlme_start_req, supplicant calls set_ap_wps_ie() to send the vendor IEs for each
428 * beacon, probe response and association response. As we get all of them in mlme_start_req, ignoring the
429 * same which comes before adding GO VIF
430 */
431 if (!ndev_vif->activated) {
432 SLSI_DBG1(sdev, SLSI_CFG80211, "vif not activated\n");
433 result = 0;
434 goto exit;
435 }
436 if (!(ndev_vif->iftype == NL80211_IFTYPE_P2P_GO || ndev_vif->iftype == NL80211_IFTYPE_AP)) {
437 SLSI_ERR(sdev, "Not AP or P2P interface. interfaceType:%d\n", ndev_vif->iftype);
438 result = -EINVAL;
439 goto exit;
440 }
441
442 vendor_ie = kmalloc(ie_len, GFP_KERNEL);
443 if (!vendor_ie) {
444 SLSI_ERR(sdev, "kmalloc failed\n");
445 result = -ENOMEM;
446 goto exit;
447 }
448 memcpy(vendor_ie, ie, ie_len);
449
450 slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len);
451 result = slsi_ap_prepare_add_info_ies(ndev_vif, vendor_ie, ie_len);
452
453 if (result == 0)
454 result = slsi_mlme_add_info_elements(sdev, dev, purpose, ndev_vif->ap.add_info_ies, ndev_vif->ap.add_info_ies_len);
455
456 slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len);
457 kfree(vendor_ie);
458
459exit:
460 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
461 return result;
462}
463
464static ssize_t slsi_set_ap_p2p_wps_ie(struct net_device *dev, char *command, int buf_len)
465{
466 struct netdev_vif *ndev_vif = netdev_priv(dev);
467 struct slsi_dev *sdev = ndev_vif->sdev;
468 int readbyte = 0;
469 int offset = 0;
470 int result = 0;
471 enum if_type {
472 IF_TYPE_NONE,
473 IF_TYPE_P2P_DEVICE,
474 IF_TYPE_AP_P2P
475 } iftype = IF_TYPE_NONE;
476 enum frame_type {
477 FRAME_TYPE_NONE,
478 FRAME_TYPE_BEACON,
479 FRAME_TYPE_PROBE_RESPONSE,
480 FRAME_TYPE_ASSOC_RESPONSE
481 } frametype = FRAME_TYPE_NONE;
482 u8 *params = command + strlen(CMD_SETAPP2PWPSIE) + 1;
483 int params_len = buf_len - strlen(CMD_SETAPP2PWPSIE) - 1;
484
485 readbyte = slsi_str_to_int(&params[offset], (int *)&frametype);
486 if (!readbyte) {
487 SLSI_ERR(sdev, "frametype: failed to read a numeric value\n");
488 result = -EINVAL;
489 goto exit;
490 }
491 offset = offset + readbyte + 1;
492 readbyte = slsi_str_to_int(&params[offset], (int *)&iftype);
493 if (!readbyte) {
494 SLSI_ERR(sdev, "iftype: failed to read a numeric value\n");
495 result = -EINVAL;
496 goto exit;
497 }
498 offset = offset + readbyte + 1;
499 params_len = params_len - offset;
500
501 SLSI_NET_DBG2(dev, SLSI_NETDEV,
502 "command=%s, frametype=%d, iftype=%d, total buf_len=%d, params_len=%d\n",
503 command, frametype, iftype, buf_len, params_len);
504
505 /* check the net device interface type */
506 if (iftype == IF_TYPE_P2P_DEVICE) {
507 u8 *probe_resp_ie = NULL; /* params+offset; */
508
509 if (frametype != FRAME_TYPE_PROBE_RESPONSE) {
510 SLSI_NET_ERR(dev, "Wrong frame type received\n");
511 goto exit;
512 }
513 probe_resp_ie = kmalloc(params_len, GFP_KERNEL);
514 if (probe_resp_ie == NULL) {
515 SLSI_ERR(sdev, "Malloc for IEs failed\n");
516 return -ENOMEM;
517 }
518
519 memcpy(probe_resp_ie, params+offset, params_len);
520
521 return slsi_p2p_dev_probe_rsp_ie(sdev, dev, probe_resp_ie, params_len);
522 } else if (iftype == IF_TYPE_AP_P2P) {
523 if (frametype == FRAME_TYPE_BEACON)
524 return slsi_ap_vendor_ies_write(sdev, dev, params + offset, params_len, FAPI_PURPOSE_BEACON);
525 else if (frametype == FRAME_TYPE_PROBE_RESPONSE)
526 return slsi_ap_vendor_ies_write(sdev, dev, params + offset, params_len,
527 FAPI_PURPOSE_PROBE_RESPONSE);
528 else if (frametype == FRAME_TYPE_ASSOC_RESPONSE)
529 return slsi_ap_vendor_ies_write(sdev, dev, params + offset, params_len,
530 FAPI_PURPOSE_ASSOCIATION_RESPONSE);
531 }
532exit:
533 return result;
534}
535
536/**
537 * P2P_LO_START handling.
538 * Add unsync vif, register for action frames and set the listen channel.
539 * The probe response IEs would be configured later.
540 */
541static int slsi_p2p_lo_start(struct net_device *dev, char *command)
542{
543 struct netdev_vif *ndev_vif = netdev_priv(dev);
544 struct slsi_dev *sdev = ndev_vif->sdev;
545 struct ieee80211_channel *chan = NULL;
546 char *lo_params = NULL;
547 unsigned int channel, duration, interval, count;
548 int ret = 0;
549 int freq;
550 int readbyte = 0;
551 enum nl80211_band band;
552 int offset = 0;
553
554 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
555
556 /* Reject LO if other operations are in progress. Back to back LO can be received.
557 * In such a case, if state is Listening then the listen offload flag should be true else
558 * reject the request as the Listening state would then be due to ROC.
559 */
560 if ((sdev->p2p_state == P2P_SCANNING) || (sdev->p2p_state > P2P_LISTENING) ||
561 ((sdev->p2p_state == P2P_LISTENING) && (!ndev_vif->unsync.listen_offload))) {
562 SLSI_NET_ERR(dev, "Reject LO due to ongoing P2P operation (state: %s)\n", slsi_p2p_state_text(sdev->p2p_state));
563 ret = -EINVAL;
564 goto exit;
565 }
566
567 lo_params = command + strlen(CMD_P2PLOSTART) + 1;
568 readbyte = slsi_str_to_int(&lo_params[offset], &channel);
569 if (!readbyte) {
570 SLSI_ERR(sdev, "channel: failed to read a numeric value\n");
571 ret = -EINVAL;
572 goto exit;
573 }
574 offset = offset + readbyte + 1;
575 readbyte = slsi_str_to_int(&lo_params[offset], &duration);
576 if (!readbyte) {
577 SLSI_ERR(sdev, "duration: failed to read a numeric value\n");
578 ret = -EINVAL;
579 goto exit;
580 }
581 offset = offset + readbyte + 1;
582 readbyte = slsi_str_to_int(&lo_params[offset], &interval);
583 if (!readbyte) {
584 SLSI_ERR(sdev, "interval: failed to read a numeric value\n");
585 ret = -EINVAL;
586 goto exit;
587 }
588 offset = offset + readbyte + 1;
589 readbyte = slsi_str_to_int(&lo_params[offset], &count);
590 if (!readbyte) {
591 SLSI_ERR(sdev, "count: failed to read a numeric value\n");
592 ret = -EINVAL;
593 goto exit;
594 }
595
596 if (!ndev_vif->activated) {
597 ret = slsi_mlme_add_vif(sdev, dev, dev->dev_addr, dev->dev_addr);
598 if (ret != 0) {
599 SLSI_NET_ERR(dev, "Unsync vif addition failed\n");
600 goto exit;
601 }
602
603 ndev_vif->activated = true;
604 ndev_vif->mgmt_tx_data.exp_frame = SLSI_P2P_PA_INVALID;
605 SLSI_P2P_STATE_CHANGE(sdev, P2P_IDLE_VIF_ACTIVE);
606
607 ret = slsi_mlme_register_action_frame(sdev, dev, SLSI_ACTION_FRAME_PUBLIC, SLSI_ACTION_FRAME_PUBLIC);
608 if (ret != 0) {
609 SLSI_NET_ERR(dev, "Action frame registration for unsync vif failed\n");
610 goto exit_with_vif_deactivate;
611 }
612 }
613
614 /* Send set_channel irrespective of the values of LO parameters as they are not cached
615 * in driver to check whether they have changed.
616 */
617 band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
618 freq = ieee80211_channel_to_frequency(channel, band);
619 chan = ieee80211_get_channel(sdev->wiphy, freq);
620 if (!chan) {
621 SLSI_NET_ERR(dev, "Incorrect channel: %u - Listen Offload failed\n", channel);
622 ret = -EINVAL;
623 goto exit_with_vif_deactivate;
624 }
625
626 ret = slsi_mlme_set_channel(sdev, dev, chan, duration, interval, count);
627 if (ret != 0) {
628 SLSI_NET_ERR(dev, "Set channel for unsync vif failed\n");
629 goto exit_with_vif_deactivate;
630 } else {
631 ndev_vif->chan = chan;
632 ndev_vif->driver_channel = chan->hw_value;
633 }
634 /* If framework sends the values for listen offload as 1,500,5000 and 6,
635 * where 5000ms (5 seconds) is the listen interval which needs to be repeated
636 * 6 times(i.e. count). Hence listen_end_ind comes after 30 seconds
637 * (6 * 5000 = 30000ms) Hence host should wait 31 seconds to delete the
638 * unsync VIF for one such P2P listen offload request.
639 */
640 slsi_p2p_queue_unsync_vif_del_work(ndev_vif, interval * count + 1000);
641 ndev_vif->unsync.listen_offload = true;
642 SLSI_P2P_STATE_CHANGE(ndev_vif->sdev, P2P_LISTENING);
643 goto exit;
644
645exit_with_vif_deactivate:
646 slsi_p2p_vif_deactivate(sdev, dev, true);
647exit:
648 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
649 return ret;
650}
651
652/**
653 * P2P_LO_STOP handling.
654 * Clear listen offload flag.
655 * Delete the P2P unsynchronized vif.
656 */
657static int slsi_p2p_lo_stop(struct net_device *dev)
658{
659 struct netdev_vif *ndev_vif = netdev_priv(dev);
660
661 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
662
663 WARN_ON((!ndev_vif->unsync.listen_offload) || (ndev_vif->sdev->p2p_state != P2P_LISTENING));
664
665 ndev_vif->unsync.listen_offload = false;
666
667 /* Deactivating the p2p unsynchronized vif */
668 if (ndev_vif->sdev->p2p_state == P2P_LISTENING)
669 slsi_p2p_vif_deactivate(ndev_vif->sdev, ndev_vif->wdev.netdev, true);
670
671 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
672
673 return 0;
674}
675
676static ssize_t slsi_rx_filter_num_write(struct net_device *dev, int add_remove, int filter_num)
677{
678 struct netdev_vif *ndev_vif = netdev_priv(dev);
679 struct slsi_dev *sdev = ndev_vif->sdev;
680 int ret = 0;
681
682 if (add_remove)
683 sdev->device_config.rx_filter_num = filter_num;
684 else
685 sdev->device_config.rx_filter_num = 0;
686 return ret;
687}
688
689#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING
690#if !defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION < 90000)
691static ssize_t slsi_create_interface(struct net_device *dev, char *intf_name)
692{
693 struct netdev_vif *ndev_vif = netdev_priv(dev);
694 struct slsi_dev *sdev = ndev_vif->sdev;
695 struct net_device *ap_dev;
696
697 ap_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN);
698 if (ap_dev && (strcmp(ap_dev->name, intf_name) == 0)) {
699 SLSI_NET_ERR(dev, "%s already created\n", intf_name);
700 return -EINVAL;
701 }
702
703 ap_dev = slsi_dynamic_interface_create(sdev->wiphy, intf_name, NL80211_IFTYPE_AP, NULL);
704 if (ap_dev) {
705 sdev->netdev_ap = ap_dev;
706 return 0;
707 }
708
709 SLSI_NET_ERR(dev, "Failed to create AP interface %s\n", intf_name);
710 return -EINVAL;
711}
712
713static ssize_t slsi_delete_interface(struct net_device *dev, char *intf_name)
714{
715 struct netdev_vif *ndev_vif = netdev_priv(dev);
716 struct slsi_dev *sdev = ndev_vif->sdev;
717
718 if (strcmp(intf_name, CONFIG_SCSC_AP_INTERFACE_NAME) == 0)
719 dev = sdev->netdev[SLSI_NET_INDEX_P2PX_SWLAN];
720
721 if (!dev) {
722 SLSI_WARN(sdev, "AP dev is NULL");
723 return -EINVAL;
724 }
725 ndev_vif = netdev_priv(dev);
726
727 if (ndev_vif->activated)
728 slsi_stop_net_dev(sdev, dev);
729 slsi_netif_remove_rtlnl_locked(sdev, dev);
730
731 sdev->netdev_ap = NULL;
732 SLSI_DBG1_NODEV(SLSI_MLME, "Successfully deleted AP interface %s ", intf_name);
733
734 return 0;
735}
736#endif
737
738static ssize_t slsi_set_indoor_channels(struct net_device *dev, char *arg)
739{
740 struct netdev_vif *ndev_vif = netdev_priv(dev);
741 struct slsi_dev *sdev = ndev_vif->sdev;
742 int readbyte = 0;
743 int offset = 0;
744 int res;
745 int ret;
746
747 readbyte = slsi_str_to_int(&arg[offset], &res);
748
749 ret = slsi_set_mib_wifi_sharing_5ghz_channel(sdev, SLSI_PSID_UNIFI_WI_FI_SHARING5_GHZ_CHANNEL,
750 res, offset, readbyte, arg);
751
752 return ret;
753}
754
755static ssize_t slsi_get_indoor_channels(struct net_device *dev, char *command, int buf_len)
756{
757 struct netdev_vif *ndev_vif = netdev_priv(dev);
758 struct slsi_dev *sdev = ndev_vif->sdev;
759 char op[150] = "";
760 char int_string[30] = "";
761 int i;
762 int len = 0;
763
764 SLSI_DBG1_NODEV(SLSI_MLME, "GET_INDOOR_CHANNELS : %d ", sdev->num_5g_restricted_channels);
765
766 for (i = 0; i < sdev->num_5g_restricted_channels; i++) {
767 sprintf(int_string, "%d", sdev->wifi_sharing_5g_restricted_channels[i]);
768 strcat(op, int_string);
769 strcat(op, " ");
770 }
771
772 len = snprintf(command, buf_len, "%d %s", sdev->num_5g_restricted_channels, op);
773
774 return len;
775}
776#endif
777static ssize_t slsi_set_country_rev(struct net_device *dev, char *country_code)
778{
779 struct netdev_vif *ndev_vif = netdev_priv(dev);
780 struct slsi_dev *sdev = ndev_vif->sdev;
781 char alpha2_rev[4];
782 int status = 0;
783
784 if (!country_code)
785 return -EINVAL;
786
787 memcpy(alpha2_rev, country_code, 4);
788
789 status = slsi_set_country_update_regd(sdev, alpha2_rev, 4);
790
791 return status;
792}
793
794static ssize_t slsi_get_country_rev(struct net_device *dev, char *command, int buf_len)
795{
796 struct netdev_vif *ndev_vif = netdev_priv(dev);
797 struct slsi_dev *sdev = ndev_vif->sdev;
798 u8 buf[5];
799 int len = 0;
800
801 memset(buf, 0, sizeof(buf));
802
803 len = snprintf(command, buf_len, "%s %c%c %d", CMD_GETCOUNTRYREV,
804 sdev->device_config.domain_info.regdomain->alpha2[0],
805 sdev->device_config.domain_info.regdomain->alpha2[1],
806 sdev->device_config.domain_info.regdomain->dfs_region);
807
808 return len;
809}
810
811#ifdef CONFIG_SCSC_WLAN_WES_NCHO
812static ssize_t slsi_roam_scan_trigger_write(struct net_device *dev, char *command, int buf_len)
813{
814 struct netdev_vif *ndev_vif = netdev_priv(dev);
815 struct slsi_dev *sdev = ndev_vif->sdev;
816 int mib_value = 0;
817
818 slsi_str_to_int(command, &mib_value);
819
820 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_RSSI_ROAM_SCAN_TRIGGER, mib_value);
821}
822
823static ssize_t slsi_roam_scan_trigger_read(struct net_device *dev, char *command, int buf_len)
824{
825 struct netdev_vif *ndev_vif = netdev_priv(dev);
826 struct slsi_dev *sdev = ndev_vif->sdev;
827 int mib_value = 0;
828 int res;
829
830 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_RSSI_ROAM_SCAN_TRIGGER, &mib_value);
831 if (res)
832 return res;
833 res = snprintf(command, buf_len, "%s %d", CMD_GETROAMTRIGGER, mib_value);
834 return res;
835}
836
837static ssize_t slsi_roam_delta_trigger_write(struct net_device *dev, char *command, int buf_len)
838{
839 struct netdev_vif *ndev_vif = netdev_priv(dev);
840 struct slsi_dev *sdev = ndev_vif->sdev;
841 int mib_value = 0;
842
843 slsi_str_to_int(command, &mib_value);
844
845 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_DELTA_TRIGGER, mib_value);
846}
847
848static ssize_t slsi_roam_delta_trigger_read(struct net_device *dev, char *command, int buf_len)
849{
850 struct netdev_vif *ndev_vif = netdev_priv(dev);
851 struct slsi_dev *sdev = ndev_vif->sdev;
852 int mib_value = 0;
853 int res;
854
855 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_DELTA_TRIGGER, &mib_value);
856 if (res)
857 return res;
858
859 res = snprintf(command, buf_len, "%s %d", CMD_GETROAMDELTA, mib_value);
860 return res;
861}
862
863static ssize_t slsi_cached_channel_scan_period_write(struct net_device *dev, char *command, int buf_len)
864{
865 struct netdev_vif *ndev_vif = netdev_priv(dev);
866 struct slsi_dev *sdev = ndev_vif->sdev;
867 int mib_value = 0;
868
869 slsi_str_to_int(command, &mib_value);
870 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_CACHED_CHANNEL_SCAN_PERIOD, mib_value * 1000000);
871}
872
873static ssize_t slsi_cached_channel_scan_period_read(struct net_device *dev, char *command, int buf_len)
874{
875 struct netdev_vif *ndev_vif = netdev_priv(dev);
876 struct slsi_dev *sdev = ndev_vif->sdev;
877 int mib_value = 0;
878 int res;
879
880 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_CACHED_CHANNEL_SCAN_PERIOD, &mib_value);
881 if (res)
882 return res;
883
884 res = snprintf(command, buf_len, "%s %d", CMD_GETROAMSCANPERIOD, mib_value / 1000000);
885
886 return res;
887}
888
889static ssize_t slsi_full_roam_scan_period_write(struct net_device *dev, char *command, int buf_len)
890{
891 struct netdev_vif *ndev_vif = netdev_priv(dev);
892 struct slsi_dev *sdev = ndev_vif->sdev;
893 int mib_value = 0;
894
895 slsi_str_to_int(command, &mib_value);
896
897 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_FULL_ROAM_SCAN_PERIOD, mib_value * 1000000);
898}
899
900static ssize_t slsi_full_roam_scan_period_read(struct net_device *dev, char *command, int buf_len)
901{
902 struct netdev_vif *ndev_vif = netdev_priv(dev);
903 struct slsi_dev *sdev = ndev_vif->sdev;
904 int mib_value = 0;
905 int res;
906
907 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_FULL_ROAM_SCAN_PERIOD, &mib_value);
908 if (res)
909 return res;
910
911 res = snprintf(command, buf_len, "%s %d", CMD_GETFULLROAMSCANPERIOD, mib_value / 1000000);
912
913 return res;
914}
915
916static ssize_t slsi_roam_scan_max_active_channel_time_write(struct net_device *dev, char *command, int buf_len)
917{
918 struct netdev_vif *ndev_vif = netdev_priv(dev);
919 struct slsi_dev *sdev = ndev_vif->sdev;
920 int mib_value = 0;
921
922 slsi_str_to_int(command, &mib_value);
923
924 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_MAX_ACTIVE_CHANNEL_TIME, mib_value);
925}
926
927static ssize_t slsi_roam_scan_max_active_channel_time_read(struct net_device *dev, char *command, int buf_len)
928{
929 struct netdev_vif *ndev_vif = netdev_priv(dev);
930 struct slsi_dev *sdev = ndev_vif->sdev;
931 int mib_value = 0;
932 int res;
933
934 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_MAX_ACTIVE_CHANNEL_TIME, &mib_value);
935 if (res)
936 return res;
937
938 res = snprintf(command, buf_len, "%s %d", CMD_GETSCANCHANNELTIME, mib_value);
939
940 return res;
941}
942
943static ssize_t slsi_roam_scan_probe_interval_write(struct net_device *dev, char *command, int buf_len)
944{
945 struct netdev_vif *ndev_vif = netdev_priv(dev);
946 struct slsi_dev *sdev = ndev_vif->sdev;
947 int mib_value = 0;
948
949 slsi_str_to_int(command, &mib_value);
950 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_NPROBE, mib_value);
951}
952
953static ssize_t slsi_roam_scan_probe_interval_read(struct net_device *dev, char *command, int buf_len)
954{
955 struct netdev_vif *ndev_vif = netdev_priv(dev);
956 struct slsi_dev *sdev = ndev_vif->sdev;
957 int mib_value = 0;
958 int res;
959
960 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_NPROBE, &mib_value);
961 if (res)
962 return res;
963
964 res = snprintf(command, buf_len, "%s %d", CMD_GETSCANNPROBES, mib_value);
965
966 return res;
967}
968
969static ssize_t slsi_roam_mode_write(struct net_device *dev, char *command, int buf_len)
970{
971 struct netdev_vif *ndev_vif = netdev_priv(dev);
972 struct slsi_dev *sdev = ndev_vif->sdev;
973 int mib_value = 0;
974
975 if (slsi_is_rf_test_mode_enabled()) {
976 SLSI_DBG1_NODEV(SLSI_MLME, "SLSI_PSID_UNIFI_ROAM_MODE is not supported because of rf test mode.\n");
977 return -ENOTSUPP;
978 }
979
980 slsi_str_to_int(command, &mib_value);
981
982 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_MODE, mib_value);
983}
984
985static ssize_t slsi_roam_mode_read(struct net_device *dev, char *command, int buf_len)
986{
987 struct netdev_vif *ndev_vif = netdev_priv(dev);
988 struct slsi_dev *sdev = ndev_vif->sdev;
989 int mib_value = 0;
990 int res;
991
992 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_MODE, &mib_value);
993 if (res)
994 return res;
995
996 res = snprintf(command, buf_len, "%s %d", CMD_GETROAMMODE, mib_value);
997
998 return res;
999}
1000
1001static int slsi_roam_offload_ap_list(struct net_device *dev, char *command, int buf_len)
1002{
1003 struct netdev_vif *ndev_vif = netdev_priv(dev);
1004 struct slsi_dev *sdev = ndev_vif->sdev;
1005 struct cfg80211_acl_data *mac_acl;
1006 int ap_count = 0;
1007 int buf_pos = 0;
1008 int i, r;
1009 int malloc_len;
1010
1011 /* command format:
1012 * x,aa:bb:cc:dd:ee:ff,xx:yy:zz:qq:ww:ee...
1013 * x = 1 to 100
1014 * each mac address id 17 bytes and every mac address is separated by ','
1015 */
1016 buf_pos = slsi_str_to_int(command, &ap_count);
1017 if (ap_count < ROAMOFFLAPLIST_MIN || ap_count > ROAMOFFLAPLIST_MAX) {
1018 SLSI_ERR(sdev, "ap_count: %d\n", ap_count);
1019 return -EINVAL;
1020 }
1021 buf_pos++;
1022 /* each mac address takes 18 bytes(17 for mac address and 1 for ',') except the last one.
1023 * the last mac address is just 17 bytes(without a coma)
1024 */
1025 if ((buf_len - buf_pos) < (ap_count*18 - 1)) {
1026 SLSI_ERR(sdev, "Invalid buff len:%d for %d APs\n", (buf_len - buf_pos), ap_count);
1027 return -EINVAL;
1028 }
1029 malloc_len = sizeof(struct cfg80211_acl_data) + sizeof(struct mac_address) * ap_count;
1030 mac_acl = kmalloc(malloc_len, GFP_KERNEL);
1031 if (!mac_acl) {
1032 SLSI_ERR(sdev, "MEM fail for size:%ld\n", sizeof(struct cfg80211_acl_data) + sizeof(struct mac_address) * ap_count);
1033 return -ENOMEM;
1034 }
1035
1036 for (i = 0; i < ap_count; i++) {
1037 slsi_machexstring_to_macarray(&command[buf_pos], mac_acl->mac_addrs[i].addr);
1038 buf_pos += 18;
1039 SLSI_DBG3_NODEV(SLSI_MLME, "[%pM]", mac_acl->mac_addrs[i].addr);
1040 }
1041 mac_acl->acl_policy = NL80211_ACL_POLICY_DENY_UNLESS_LISTED;
1042 mac_acl->n_acl_entries = ap_count;
1043
1044 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
1045 r = slsi_mlme_set_acl(sdev, dev, ndev_vif->ifnum, mac_acl);
1046 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1047 kfree(mac_acl);
1048 return r;
1049}
1050
1051static ssize_t slsi_roam_scan_band_write(struct net_device *dev, char *command, int buf_len)
1052{
1053 struct netdev_vif *ndev_vif = netdev_priv(dev);
1054 struct slsi_dev *sdev = ndev_vif->sdev;
1055 int mib_value = 0;
1056
1057 slsi_str_to_int(command, &mib_value);
1058 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_BAND, mib_value);
1059}
1060
1061static ssize_t slsi_roam_scan_band_read(struct net_device *dev, char *command, int buf_len)
1062{
1063 struct netdev_vif *ndev_vif = netdev_priv(dev);
1064 struct slsi_dev *sdev = ndev_vif->sdev;
1065 int mib_value = 0;
1066 int res;
1067
1068 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_BAND, &mib_value);
1069 if (res)
1070 return res;
1071
1072 res = snprintf(command, buf_len, "%s %d", CMD_GETROAMINTRABAND, mib_value);
1073
1074 return res;
1075}
1076
1077static ssize_t slsi_freq_band_write(struct net_device *dev, uint band)
1078{
1079 struct netdev_vif *ndev_vif = netdev_priv(dev);
1080 struct slsi_dev *sdev = ndev_vif->sdev;
1081
1082 slsi_band_update(sdev, band);
1083 /* Convert to correct Mib value (intra_band:1, all_band:2) */
1084 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_BAND, (band == SLSI_FREQ_BAND_AUTO) ? 2 : 1);
1085}
1086
1087static ssize_t slsi_freq_band_read(struct net_device *dev, char *command, int buf_len)
1088{
1089 struct netdev_vif *ndev_vif = netdev_priv(dev);
1090 struct slsi_dev *sdev = ndev_vif->sdev;
1091 char buf[128];
1092 int pos = 0;
1093 const size_t bufsz = sizeof(buf);
1094
1095 memset(buf, '\0', 128);
1096 pos += scnprintf(buf + pos, bufsz - pos, "Band %d", sdev->device_config.supported_band);
1097
1098 buf[pos] = '\0';
1099 memcpy(command, buf, pos + 1);
1100
1101 return pos;
1102}
1103
1104static ssize_t slsi_roam_scan_control_write(struct net_device *dev, int mode)
1105{
1106 struct netdev_vif *ndev_vif = netdev_priv(dev);
1107 struct slsi_dev *sdev = ndev_vif->sdev;
1108
1109 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1110
1111 if (mode == 0 || mode == 1) {
1112 sdev->device_config.roam_scan_mode = mode;
1113 } else {
1114 SLSI_ERR(sdev, "Invalid roam Mode: Must be 0 or, 1 Not '%c'\n", mode);
1115 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1116 return -EINVAL;
1117 }
1118
1119 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1120 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_CONTROL, sdev->device_config.roam_scan_mode);
1121}
1122
1123static ssize_t slsi_roam_scan_control_read(struct net_device *dev, char *command, int buf_len)
1124{
1125 struct netdev_vif *ndev_vif = netdev_priv(dev);
1126 struct slsi_dev *sdev = ndev_vif->sdev;
1127 int mib_value = 0;
1128 int res;
1129
1130 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_CONTROL, &mib_value);
1131 if (res)
1132 return res;
1133
1134 res = snprintf(command, buf_len, "%s %d", CMD_GETROAMSCANCONTROL, mib_value);
1135
1136 return res;
1137}
1138
1139static ssize_t slsi_roam_scan_home_time_write(struct net_device *dev, char *command, int buf_len)
1140{
1141 struct netdev_vif *ndev_vif = netdev_priv(dev);
1142 struct slsi_dev *sdev = ndev_vif->sdev;
1143 int mib_value = 0;
1144
1145 slsi_str_to_int(command, &mib_value);
1146
1147 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_HOME_TIME, mib_value);
1148}
1149
1150static ssize_t slsi_roam_scan_home_time_read(struct net_device *dev, char *command, int buf_len)
1151{
1152 struct netdev_vif *ndev_vif = netdev_priv(dev);
1153 struct slsi_dev *sdev = ndev_vif->sdev;
1154 int mib_value = 0;
1155 int res;
1156
1157 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_HOME_TIME, &mib_value);
1158 if (res)
1159 return res;
1160
1161 res = snprintf(command, buf_len, "%s %d", CMD_GETSCANHOMETIME, mib_value);
1162
1163 return res;
1164}
1165
1166static ssize_t slsi_roam_scan_home_away_time_write(struct net_device *dev, char *command, int buf_len)
1167{
1168 struct netdev_vif *ndev_vif = netdev_priv(dev);
1169 struct slsi_dev *sdev = ndev_vif->sdev;
1170 int mib_value = 0;
1171
1172 slsi_str_to_int(command, &mib_value);
1173 return slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAM_SCAN_HOME_AWAY_TIME, mib_value);
1174}
1175
1176static ssize_t slsi_roam_scan_home_away_time_read(struct net_device *dev, char *command, int buf_len)
1177{
1178 struct netdev_vif *ndev_vif = netdev_priv(dev);
1179 struct slsi_dev *sdev = ndev_vif->sdev;
1180 int mib_value = 0;
1181 int res;
1182
1183 res = slsi_get_mib_roam(sdev, SLSI_PSID_UNIFI_ROAM_SCAN_HOME_AWAY_TIME, &mib_value);
1184 if (res)
1185 return res;
1186
1187 res = snprintf(command, buf_len, "%s %d", CMD_GETSCANHOMEAWAYTIME, mib_value);
1188
1189 return res;
1190}
1191
1192static ssize_t slsi_roam_scan_channels_write(struct net_device *dev, char *command, int buf_len)
1193{
1194 struct netdev_vif *ndev_vif = netdev_priv(dev);
1195 struct slsi_dev *sdev = ndev_vif->sdev;
1196 int result = 0;
1197 int i, channel_count;
1198 int offset = 0;
1199 int readbyte = 0;
1200 int channels[MAX_CHANNEL_LIST];
1201
1202 readbyte = slsi_str_to_int(command, &channel_count);
1203
1204 if (!readbyte) {
1205 SLSI_ERR(sdev, "channel count: failed to read a numeric value");
1206 return -EINVAL;
1207 }
1208 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1209
1210 if (channel_count > MAX_CHANNEL_LIST)
1211 channel_count = MAX_CHANNEL_LIST;
1212 sdev->device_config.wes_roam_scan_list.n = channel_count;
1213
1214 for (i = 0; i < channel_count; i++) {
1215 offset = offset + readbyte + 1;
1216 readbyte = slsi_str_to_int(&command[offset], &channels[i]);
1217 if (!readbyte) {
1218 SLSI_ERR(sdev, "failed to read a numeric value\n");
1219 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1220 return -EINVAL;
1221 }
1222
1223 sdev->device_config.wes_roam_scan_list.channels[i] = channels[i];
1224 }
1225 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1226
1227 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
1228 result = slsi_mlme_set_cached_channels(sdev, dev, channel_count, sdev->device_config.wes_roam_scan_list.channels);
1229 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1230
1231 return result;
1232}
1233
1234static ssize_t slsi_roam_scan_channels_read(struct net_device *dev, char *command, int buf_len)
1235{
1236 struct netdev_vif *ndev_vif = netdev_priv(dev);
1237 struct slsi_dev *sdev = ndev_vif->sdev;
1238 char channel_buf[128] = { 0 };
1239 int pos = 0;
1240 int i;
1241 int channel_count = 0;
1242
1243 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1244 channel_count = sdev->device_config.wes_roam_scan_list.n;
1245 pos = scnprintf(channel_buf, sizeof(channel_buf), "%s %d", CMD_GETROAMSCANCHANNELS, channel_count);
1246 for (i = 0; i < channel_count; i++)
1247 pos += scnprintf(channel_buf + pos, sizeof(channel_buf) - pos, " %d", sdev->device_config.wes_roam_scan_list.channels[i]);
1248 channel_buf[pos] = '\0';
1249
1250 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1251
1252 memcpy(command, channel_buf, pos + 1);
1253
1254 return pos;
1255}
1256
1257static ssize_t slsi_okc_mode_write(struct net_device *dev, int mode)
1258{
1259 struct netdev_vif *ndev_vif = netdev_priv(dev);
1260 struct slsi_dev *sdev = ndev_vif->sdev;
1261
1262 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1263
1264 if (mode == 0 || mode == 1) {
1265 sdev->device_config.okc_mode = mode;
1266 } else {
1267 SLSI_ERR(sdev, "Invalid OKC Mode: Must be 0 or, 1 Not '%c'\n", mode);
1268 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1269 return -EINVAL;
1270 }
1271
1272 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1273 return 0;
1274}
1275
1276static ssize_t slsi_okc_mode_read(struct net_device *dev, char *command, int buf_len)
1277{
1278 struct netdev_vif *ndev_vif = netdev_priv(dev);
1279 struct slsi_dev *sdev = ndev_vif->sdev;
1280 int okc_mode;
1281 int res;
1282
1283 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1284 okc_mode = sdev->device_config.okc_mode;
1285 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1286
1287 res = snprintf(command, buf_len, "%s %d", CMD_GETOKCMODE, okc_mode);
1288
1289 return res;
1290}
1291
1292static ssize_t slsi_wes_mode_write(struct net_device *dev, int mode)
1293{
1294 struct netdev_vif *ndev_vif = netdev_priv(dev);
1295 struct slsi_dev *sdev = ndev_vif->sdev;
1296 int result = 0;
1297 u32 action_frame_bmap = SLSI_STA_ACTION_FRAME_BITMAP;
1298
1299 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1300
1301 if (mode == 0 || mode == 1) {
1302 sdev->device_config.wes_mode = mode;
1303 } else {
1304 SLSI_ERR(sdev, "Invalid WES Mode: Must be 0 or 1 Not '%c'\n", mode);
1305 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1306 return -EINVAL;
1307 }
1308 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1309 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
1310
1311 if ((ndev_vif->activated) && (ndev_vif->vif_type == FAPI_VIFTYPE_STATION) &&
1312 (ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) {
1313 if (sdev->device_config.wes_mode)
1314 action_frame_bmap |= SLSI_ACTION_FRAME_VENDOR_SPEC;
1315
1316 result = slsi_mlme_register_action_frame(sdev, dev, action_frame_bmap, action_frame_bmap);
1317 }
1318
1319 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1320
1321 return result;
1322}
1323
1324static ssize_t slsi_wes_mode_read(struct net_device *dev, char *command, int buf_len)
1325{
1326 struct netdev_vif *ndev_vif = netdev_priv(dev);
1327 struct slsi_dev *sdev = ndev_vif->sdev;
1328 int wes_mode;
1329 int res;
1330
1331 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1332 wes_mode = sdev->device_config.wes_mode;
1333 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1334
1335 res = snprintf(command, buf_len, "%s %d", CMD_GETWESMODE, wes_mode);
1336
1337 return res;
1338}
1339#endif
1340
1341static ssize_t slsi_set_pmk(struct net_device *dev, char *command, int buf_len)
1342{
1343 struct netdev_vif *ndev_vif = netdev_priv(dev);
1344 struct slsi_dev *sdev = ndev_vif->sdev;
1345 u8 pmk[33];
1346 int result = 0;
1347
1348 memcpy((u8 *)pmk, command + strlen("SET_PMK "), 32);
1349 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
1350
1351 result = slsi_mlme_set_pmk(sdev, dev, pmk, 32);
1352
1353 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1354 return result;
1355}
1356
1357static ssize_t slsi_auto_chan_read(struct net_device *dev, char *command, int buf_len)
1358{
1359 struct netdev_vif *ndev_vif = netdev_priv(dev);
1360 struct slsi_dev *sdev = ndev_vif->sdev;
1361 int ap_auto_chan;
1362 int result = 0;
1363
1364 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1365 ap_auto_chan = sdev->device_config.ap_auto_chan;
1366 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1367
1368 result = snprintf(command, buf_len, "%d\n", ap_auto_chan);
1369 return result;
1370}
1371
1372static ssize_t slsi_auto_chan_write(struct net_device *dev, char *command)
1373{
1374 struct netdev_vif *ndev_vif = netdev_priv(dev);
1375 struct slsi_dev *sdev = ndev_vif->sdev;
1376 int n_channels;
1377 struct ieee80211_channel *channels[SLSI_NO_OF_SCAN_CHANLS_FOR_AUTO_CHAN_MAX] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
1378 int count_channels;
1379 int offset;
1380 int chan;
1381 int index = 0;
1382#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING
1383 struct net_device *sta_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN);
1384 struct netdev_vif *ndev_sta_vif = netdev_priv(sta_dev);
1385 int sta_frequency;
1386#endif
1387
1388 offset = slsi_str_to_int(&command[index], &n_channels);
1389 if (!offset) {
1390 SLSI_ERR(sdev, "channel count: failed to read a numeric value");
1391 return -EINVAL;
1392 }
1393
1394 if (n_channels > SLSI_NO_OF_SCAN_CHANLS_FOR_AUTO_CHAN_MAX) {
1395 SLSI_ERR(sdev, "channel count:%d > SLSI_NO_OF_SCAN_CHANLS_FOR_AUTO_CHAN_MAX:%d\n", n_channels, SLSI_NO_OF_SCAN_CHANLS_FOR_AUTO_CHAN_MAX);
1396 return -EINVAL;
1397 }
1398
1399 /* If "1 6 11" are passed, scan all "1 - 14" channels. If "1 6" are passed, scan "1 - 9" channels */
1400 if (n_channels == 3)
1401 n_channels = 14;
1402 else if (n_channels == 2)
1403 n_channels = 9;
1404 count_channels = 0;
1405 for (chan = 1; chan <= n_channels; chan++) {
1406 int center_freq;
1407
1408 center_freq = ieee80211_channel_to_frequency(chan, NL80211_BAND_2GHZ);
1409 channels[count_channels] = ieee80211_get_channel(sdev->wiphy, center_freq);
1410 if (!channels[count_channels])
1411 SLSI_WARN(sdev, "channel number:%d invalid\n", chan);
1412 else
1413 count_channels++;
1414
1415 }
1416
1417 SLSI_DBG3(sdev, SLSI_INIT_DEINIT, "Number of channels for autochannel selection= %d", count_channels);
1418
1419 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1420 sdev->device_config.ap_auto_chan = 0;
1421 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1422
1423#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING
1424if ((ndev_sta_vif->activated) && (ndev_sta_vif->vif_type == FAPI_VIFTYPE_STATION) &&
1425 (ndev_sta_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTING ||
1426 ndev_sta_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) {
1427 sta_frequency = ndev_sta_vif->chan->center_freq;
1428 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1429 if ((sta_frequency / 1000) == 2)
1430 sdev->device_config.ap_auto_chan = ieee80211_frequency_to_channel(sta_frequency);
1431 else
1432 sdev->device_config.ap_auto_chan = 1;
1433 SLSI_INFO(sdev, "Channel selected = %d", sdev->device_config.ap_auto_chan);
1434 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1435 return 0;
1436}
1437#endif /*wifi sharing*/
1438 return slsi_auto_chan_select_scan(sdev, count_channels, channels);
1439}
1440
1441static ssize_t slsi_reassoc_write(struct net_device *dev, char *command, int buf_len)
1442{
1443 struct netdev_vif *ndev_vif = netdev_priv(dev);
1444 struct slsi_dev *sdev = ndev_vif->sdev;
1445 u8 bssid[6] = { 0 };
1446 int channel;
1447 int freq;
1448 enum nl80211_band band = NL80211_BAND_2GHZ;
1449 int r = 0;
1450
1451 if (command[17] != ' ') {
1452 SLSI_ERR(sdev, "Invalid Format '%s' '%c'\n", command, command[17]);
1453 return -EINVAL;
1454 }
1455
1456 command[17] = '\0';
1457
1458 slsi_machexstring_to_macarray(command, bssid);
1459
1460 if (!slsi_str_to_int(&command[18], &channel)) {
1461 SLSI_ERR(sdev, "Invalid channel string: '%s'\n", &command[18]);
1462 return -EINVAL;
1463 }
1464
1465 if (channel > 14)
1466 band = NL80211_BAND_5GHZ;
1467 freq = (u16)ieee80211_channel_to_frequency(channel, band);
1468
1469 ndev_vif = netdev_priv(dev);
1470 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
1471
1472 r = slsi_mlme_roam(sdev, dev, bssid, freq);
1473
1474 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1475 return r;
1476}
1477
1478static ssize_t slsi_send_action_frame(struct net_device *dev, char *command, int buf_len)
1479{
1480 struct netdev_vif *ndev_vif = netdev_priv(dev);
1481 struct slsi_dev *sdev = ndev_vif->sdev;
1482 char *temp;
1483 u8 bssid[6] = { 0 };
1484 int channel = 0;
1485 int freq = 0;
1486 enum nl80211_band band = NL80211_BAND_2GHZ;
1487 int r = 0;
1488 u16 host_tag = slsi_tx_mgmt_host_tag(sdev);
1489 u32 dwell_time;
1490 struct ieee80211_hdr *hdr;
1491 u8 *buf = NULL;
1492 u8 *final_buf = NULL;
1493 u8 temp_byte;
1494 int len = 0;
1495 int final_length = 0;
1496 int i = 0, j = 0;
1497 char *pos;
1498
1499 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
1500
1501 if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) ||
1502 (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) {
1503 SLSI_ERR(sdev, "Not a STA vif or status is not CONNECTED\n");
1504 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1505 return -EINVAL;
1506 }
1507 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1508
1509 command[17] = '\0';
1510 slsi_machexstring_to_macarray(command, bssid);
1511
1512 command[17] = ' ';
1513 pos = strchr(command, ' ');
1514 if (pos == NULL)
1515 return -EINVAL;
1516 *pos++ = '\0';
1517
1518 if (!slsi_str_to_int(pos, &channel)) {
1519 SLSI_ERR(sdev, "Invalid channel string: '%s'\n", pos);
1520 return -EINVAL;
1521 }
1522 pos++;
1523
1524 if (channel > 14)
1525 band = NL80211_BAND_5GHZ;
1526 freq = (u16)ieee80211_channel_to_frequency(channel, band);
1527
1528 pos = strchr(pos, ' ');
1529 if (pos == NULL)
1530 return -EINVAL;
1531 *pos++ = '\0';
1532
1533 if (!slsi_str_to_int(pos, &dwell_time)) {
1534 SLSI_ERR(sdev, "Invalid dwell time string: '%s'\n", pos);
1535 return -EINVAL;
1536 }
1537
1538 pos = strchr(pos, ' ');
1539 if (pos == NULL)
1540 return -EINVAL;
1541 pos++;
1542
1543 /*Length of data*/
1544 temp = pos;
1545 while (*temp != '\0')
1546 temp++;
1547 len = temp - pos;
1548
1549 if (len <= 0)
1550 return -EINVAL;
1551 buf = kmalloc((len + 1) / 2, GFP_KERNEL);
1552
1553 if (buf == NULL) {
1554 SLSI_ERR(sdev, "Malloc failed\n");
1555 return -ENOMEM;
1556 }
1557 /*We receive a char buffer, convert to hex*/
1558 temp = pos;
1559 for (i = 0, j = 0; j < len; j += 2) {
1560 if (j + 1 == len)
1561 temp_byte = slsi_parse_hex(temp[j]);
1562 else
1563 temp_byte = slsi_parse_hex(temp[j]) << 4 | slsi_parse_hex(temp[j + 1]);
1564 buf[i++] = temp_byte;
1565 }
1566 len = i;
1567
1568 final_length = len + IEEE80211_HEADER_SIZE;
1569 final_buf = kmalloc(final_length, GFP_KERNEL);
1570 if (final_buf == NULL) {
1571 SLSI_ERR(sdev, "Malloc failed\n");
1572 kfree(buf);
1573 return -ENOMEM;
1574 }
1575
1576 hdr = (struct ieee80211_hdr *)final_buf;
1577 hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, IEEE80211_STYPE_ACTION);
1578 SLSI_ETHER_COPY(hdr->addr1, bssid);
1579 SLSI_ETHER_COPY(hdr->addr2, sdev->hw_addr);
1580 SLSI_ETHER_COPY(hdr->addr3, bssid);
1581 memcpy(final_buf + IEEE80211_HEADER_SIZE, buf, len);
1582
1583 kfree(buf);
1584
1585 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
1586
1587 r = slsi_mlme_send_frame_mgmt(sdev, dev, final_buf, final_length, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_ACTION, host_tag, SLSI_FREQ_HOST_TO_FW(freq), dwell_time * 1000, 0);
1588
1589 kfree(final_buf);
1590 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1591 return r;
1592}
1593
1594static ssize_t slsi_setting_max_sta_write(struct net_device *dev, int sta_number)
1595{
1596 struct netdev_vif *ndev_vif = netdev_priv(dev);
1597 struct slsi_dev *sdev = ndev_vif->sdev;
1598 struct slsi_mib_data mib_data = { 0, NULL };
1599 int result = 0;
1600
1601 if (sta_number > 10 || sta_number < 1)
1602 return -EINVAL;
1603 result = slsi_mib_encode_uint(&mib_data, SLSI_PSID_UNIFI_MAX_CLIENT, sta_number, 0);
1604 if ((result != SLSI_MIB_STATUS_SUCCESS) || (mib_data.dataLength == 0))
1605 return -ENOMEM;
1606 result = slsi_mlme_set(sdev, dev, mib_data.data, mib_data.dataLength);
1607 if (result != 0)
1608 SLSI_ERR(sdev, "max_sta: mlme_set_req failed: Result code: %d\n", result);
1609 kfree(mib_data.data);
1610
1611 return result;
1612}
1613
1614static ssize_t slsi_country_write(struct net_device *dev, char *country_code)
1615{
1616 struct netdev_vif *netdev_vif = netdev_priv(dev);
1617 struct slsi_dev *sdev = netdev_vif->sdev;
1618 char alpha2_code[SLSI_COUNTRY_CODE_LEN];
1619 int status;
1620
1621 if (strlen(country_code) < 2)
1622 return -EINVAL;
1623
1624 memcpy(alpha2_code, country_code, 2);
1625 alpha2_code[2] = ' '; /* set 3rd byte of countrycode to ASCII space */
1626
1627 status = slsi_set_country_update_regd(sdev, alpha2_code, SLSI_COUNTRY_CODE_LEN);
1628
1629 return status;
1630}
1631
1632#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON
1633static ssize_t slsi_forward_beacon(struct net_device *dev, char *action)
1634{
1635 struct netdev_vif *netdev_vif = netdev_priv(dev);
1636 struct slsi_dev *sdev = netdev_vif->sdev;
1637 int intended_action = 0;
1638 int ret = 0;
1639
1640 if (strncasecmp(action, "stop", 4) == 0) {
1641 intended_action = FAPI_ACTION_STOP;
1642 } else if (strncasecmp(action, "start", 5) == 0) {
1643 intended_action = FAPI_ACTION_START;
1644 } else {
1645 SLSI_NET_ERR(dev, "BEACON_RECV should be used with start or stop\n");
1646 return -EINVAL;
1647 }
1648
1649 SLSI_NET_DBG2(dev, SLSI_MLME, "BEACON_RECV %s!!\n", intended_action ? "START" : "STOP");
1650 SLSI_MUTEX_LOCK(netdev_vif->vif_mutex);
1651
1652 if ((!netdev_vif->activated) || (netdev_vif->vif_type != FAPI_VIFTYPE_STATION) ||
1653 (netdev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) {
1654 SLSI_ERR(sdev, "Not a STA vif or status is not CONNECTED\n");
1655 ret = -EINVAL;
1656 goto exit_vif_mutex;
1657 }
1658
1659 if (((intended_action == FAPI_ACTION_START) && netdev_vif->is_wips_running) ||
1660 ((intended_action == FAPI_ACTION_STOP) && !netdev_vif->is_wips_running)) {
1661 SLSI_NET_INFO(dev, "Forwarding beacon is already %s!!\n",
1662 netdev_vif->is_wips_running ? "running" : "stopped");
1663 ret = 0;
1664 goto exit_vif_mutex;
1665 }
1666
1667 SLSI_MUTEX_LOCK(netdev_vif->scan_mutex);
1668 if (intended_action == FAPI_ACTION_START &&
1669 (netdev_vif->scan[SLSI_SCAN_HW_ID].scan_req || netdev_vif->sta.roam_in_progress)) {
1670 SLSI_NET_ERR(dev, "Rejecting BEACON_RECV start as scan/roam is running\n");
1671 ret = -EBUSY;
1672 goto exit_scan_mutex;
1673 }
1674
1675 ret = slsi_mlme_set_forward_beacon(sdev, dev, intended_action);
1676exit_scan_mutex:
1677 SLSI_MUTEX_UNLOCK(netdev_vif->scan_mutex);
1678exit_vif_mutex:
1679 SLSI_MUTEX_UNLOCK(netdev_vif->vif_mutex);
1680 return ret;
1681}
1682#endif
1683
1684static ssize_t slsi_update_rssi_boost(struct net_device *dev, char *rssi_boost_string)
1685{
1686 struct netdev_vif *netdev_vif = netdev_priv(dev);
1687 struct slsi_dev *sdev = netdev_vif->sdev;
1688 int digit1, digit2, band, lendigit1, lendigit2;
1689 int boost = 0, length = 0, i = 0;
1690
1691 if (strlen(rssi_boost_string) < 8)
1692 return -EINVAL;
1693 for (i = 0; i < (strlen(rssi_boost_string) - 4);) {
1694 if (rssi_boost_string[i] == '0' &&
1695 rssi_boost_string[i + 1] == '4') {
1696 if (rssi_boost_string[i + 2] == '0' &&
1697 rssi_boost_string[i + 3] == '2' &&
1698 ((i + 7) < strlen(rssi_boost_string)))
1699 i = i + 4;
1700 else
1701 return -EINVAL;
1702 digit1 = slsi_parse_hex(rssi_boost_string[i]);
1703 digit2 = slsi_parse_hex(rssi_boost_string[i + 1]);
1704 boost = (digit1 * 16) + digit2;
1705 band = rssi_boost_string[i + 3] - '0';
1706 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1707 if (band == 0) {
1708 sdev->device_config.rssi_boost_2g = 0;
1709 sdev->device_config.rssi_boost_5g = 0;
1710 } else if (band == 1) {
1711 sdev->device_config.rssi_boost_2g = 0;
1712 sdev->device_config.rssi_boost_5g = boost;
1713 } else {
1714 sdev->device_config.rssi_boost_2g = boost;
1715 sdev->device_config.rssi_boost_5g = 0;
1716 }
1717 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1718 if ((netdev_vif->activated) &&
1719 (netdev_vif->vif_type == FAPI_VIFTYPE_STATION)) {
1720 return slsi_set_boost(sdev, dev);
1721 } else {
1722 return 0;
1723 }
1724 } else {
1725 i = i + 2;
1726 lendigit1 = slsi_parse_hex(rssi_boost_string[i]);
1727 lendigit2 = slsi_parse_hex(rssi_boost_string[i + 1]);
1728 length = (lendigit1 * 16) + lendigit2;
1729 i = i + (length * 2) + 2;
1730 }
1731 }
1732 return -EINVAL;
1733}
1734
1735int slsi_set_tx_power_calling(struct net_device *dev, char *command, int buf_len)
1736{
1737 struct netdev_vif *ndev_vif = netdev_priv(dev);
1738 struct slsi_dev *sdev = ndev_vif->sdev;
1739 int mode;
1740 int error = 0;
1741 u8 host_state;
1742
1743 (void)slsi_str_to_int(command, &mode);
1744 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1745 host_state = sdev->device_config.host_state;
1746
1747 if (!mode)
1748 host_state = host_state | SLSI_HOSTSTATE_SAR_ACTIVE;
1749 else
1750 host_state = host_state & ~SLSI_HOSTSTATE_SAR_ACTIVE;
1751
1752 error = slsi_mlme_set_host_state(sdev, dev, host_state);
1753 if (!error)
1754 sdev->device_config.host_state = host_state;
1755
1756 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1757
1758 return error;
1759}
1760
1761int slsi_set_tx_power_sar(struct net_device *dev, char *command, int buf_len)
1762{
1763 struct netdev_vif *ndev_vif = netdev_priv(dev);
1764 struct slsi_dev *sdev = ndev_vif->sdev;
1765 int mode;
1766 int error = 0;
1767 u8 host_state;
1768
1769 (void)slsi_str_to_int(command, &mode);
1770 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1771 host_state = sdev->device_config.host_state;
1772 host_state &= ~(SLSI_HOSTSTATE_SAR_ACTIVE | BIT(3) | BIT(4));
1773
1774 if (mode)
1775 host_state |= ((mode - 1) << 3) | SLSI_HOSTSTATE_SAR_ACTIVE;
1776
1777 error = slsi_mlme_set_host_state(sdev, dev, host_state);
1778 if (!error)
1779 sdev->device_config.host_state = host_state;
1780
1781 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1782
1783 return error;
1784}
1785
1786int slsi_get_tx_power_sar(struct net_device *dev, char *command, int buf_len)
1787{
1788 struct netdev_vif *ndev_vif = netdev_priv(dev);
1789 struct slsi_dev *sdev = ndev_vif->sdev;
1790 int len = 0;
1791 u8 host_state, index;
1792
1793 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1794 host_state = sdev->device_config.host_state;
1795
1796 if (host_state & SLSI_HOSTSTATE_SAR_ACTIVE)
1797 index = ((host_state >> 3) & 3) + 1;
1798 else
1799 index = 0;
1800
1801 len = snprintf(command, buf_len, "%u", index);
1802 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1803
1804 return len;
1805}
1806
1807static int slsi_print_regulatory(struct slsi_802_11d_reg_domain *domain_info, char *buf, int buf_len, struct slsi_supported_channels *supported_channels, int supp_chan_length)
1808{
1809 int cur_pos = 0;
1810 int i, j, k;
1811 char *dfs_region_str[] = {"unknown", "ETSI", "FCC", "JAPAN", "GLOBAL", "CHINA"};
1812 u8 dfs_region_index;
1813 struct ieee80211_reg_rule *reg_rule;
1814 int channel_start_freq = 0;
1815 int channel_end_freq = 0;
1816 int channel_start_num = 0;
1817 int channel_end_num = 0;
1818 int channel_count = 0;
1819 int channel_increment = 0;
1820 int channel_band = 0;
1821 bool display_pattern = false;
1822
1823 cur_pos = snprintf(buf, buf_len, "country %c%c:", domain_info->regdomain->alpha2[0],
1824 domain_info->regdomain->alpha2[1]);
1825 dfs_region_index = domain_info->regdomain->dfs_region <= 5 ? domain_info->regdomain->dfs_region : 0;
1826 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "DFS-%s\n", dfs_region_str[dfs_region_index]);
1827 for (i = 0; i < domain_info->regdomain->n_reg_rules; i++) {
1828 reg_rule = &domain_info->regdomain->reg_rules[i];
1829 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "\t(%d-%d @ %d), (N/A, %d)",
1830 reg_rule->freq_range.start_freq_khz/1000,
1831 reg_rule->freq_range.end_freq_khz/1000,
1832 reg_rule->freq_range.max_bandwidth_khz/1000,
1833 MBM_TO_DBM(reg_rule->power_rule.max_eirp));
1834 if (reg_rule->flags) {
1835 if (reg_rule->flags & NL80211_RRF_DFS)
1836 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", DFS");
1837#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1838 if (reg_rule->flags & NL80211_RRF_NO_OFDM)
1839 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_OFDM");
1840#endif
1841#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
1842 if (reg_rule->flags & (NL80211_RRF_PASSIVE_SCAN|NL80211_RRF_NO_IBSS))
1843 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_IR");
1844#endif
1845#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1846 if (reg_rule->flags & (NL80211_RRF_NO_IR))
1847 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_IR");
1848#endif
1849 if (reg_rule->flags & NL80211_RRF_NO_INDOOR)
1850 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_INDOOR");
1851 if (reg_rule->flags & NL80211_RRF_NO_OUTDOOR)
1852 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", NO_OUTDOOR");
1853 }
1854 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "\n");
1855 }
1856
1857 /* Display of Supported Channels for 2.4GHz and 5GHz */
1858 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "Channels:");
1859
1860 for (i = 0; i < supp_chan_length; i++) {
1861 channel_start_num = supported_channels[i].start_chan_num;
1862 channel_count = supported_channels[i].channel_count;
1863 channel_increment = supported_channels[i].increment;
1864 channel_band = supported_channels[i].band;
1865 channel_end_num = channel_start_num + ((channel_count - 1) * channel_increment);
1866 for (j = channel_start_num; j <= channel_end_num; j += channel_increment) {
1867 channel_start_freq = (ieee80211_channel_to_frequency(j, channel_band)*1000) - 10000;
1868 channel_end_freq = (ieee80211_channel_to_frequency(j, channel_band)*1000) + 10000;
1869 for (k = 0; k < domain_info->regdomain->n_reg_rules; k++) {
1870 reg_rule = &domain_info->regdomain->reg_rules[k];
1871 if ((reg_rule->freq_range.start_freq_khz <= channel_start_freq) &&
1872 (reg_rule->freq_range.end_freq_khz >= channel_end_freq)) {
1873 if (display_pattern)
1874 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, ", %d", j);
1875 else
1876 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, " %d", j);
1877 display_pattern = true;
1878 break;
1879 }
1880 }
1881 }
1882 }
1883 cur_pos += snprintf(buf + cur_pos, buf_len - cur_pos, "\n");
1884 return cur_pos;
1885}
1886
1887static int slsi_get_supported_channels(struct slsi_dev *sdev, struct net_device *dev, struct slsi_supported_channels *supported_channels)
1888{
1889 struct slsi_mib_data mibrsp = { 0, NULL };
1890 struct slsi_mib_data supported_chan_mib = { 0, NULL };
1891 struct slsi_mib_value *values = NULL;
1892 struct slsi_mib_get_entry get_values[] = {{SLSI_PSID_UNIFI_SUPPORTED_CHANNELS, { 0, 0 } } };
1893 int i, chan_count, chan_start;
1894 int supp_chan_length = 0;
1895
1896 /* Expect each mib length in response is <= 16. So assume 16 bytes for each MIB */
1897 mibrsp.dataLength = 16;
1898 mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL);
1899 if (mibrsp.data == NULL) {
1900 SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength);
1901 return 0;
1902 }
1903 values = slsi_read_mibs(sdev, dev, get_values, 1, &mibrsp);
1904 if (!values)
1905 goto exit_with_mibrsp;
1906
1907 if (values[0].type != SLSI_MIB_TYPE_OCTET) {
1908 SLSI_ERR(sdev, "Supported_Chan invalid type.");
1909 goto exit_with_values;
1910 }
1911
1912 supported_chan_mib = values[0].u.octetValue;
1913 for (i = 0; i < supported_chan_mib.dataLength / 2; i++) {
1914 chan_start = supported_chan_mib.data[i*2];
1915 chan_count = supported_chan_mib.data[i*2 + 1];
1916 if (chan_start == 1) { /* for 2.4GHz */
1917 supported_channels[supp_chan_length].start_chan_num = 1;
1918 if (!(sdev->device_config.host_state & SLSI_HOSTSTATE_CELLULAR_ACTIVE) &&
1919 chan_count > 11 && sdev->device_config.disable_ch12_ch13) {
1920 chan_count = 11;
1921 SLSI_DBG1(sdev, SLSI_CFG80211, "Channels 12 and 13 have been disabled");
1922 }
1923 supported_channels[supp_chan_length].channel_count = chan_count;
1924 supported_channels[supp_chan_length].increment = 1;
1925 supported_channels[supp_chan_length].band = NL80211_BAND_2GHZ;
1926 supp_chan_length = supp_chan_length + 1;
1927 } else { /* for 5GHz */
1928 supported_channels[supp_chan_length].start_chan_num = chan_start;
1929 supported_channels[supp_chan_length].channel_count = chan_count;
1930 supported_channels[supp_chan_length].increment = 4;
1931 supported_channels[supp_chan_length].band = NL80211_BAND_5GHZ;
1932 supp_chan_length = supp_chan_length + 1;
1933 }
1934 }
1935exit_with_values:
1936 kfree(values);
1937exit_with_mibrsp:
1938 kfree(mibrsp.data);
1939 return supp_chan_length;
1940}
1941
1942static int slsi_get_regulatory(struct net_device *dev, char *buf, int buf_len)
1943{
1944 struct netdev_vif *ndev_vif = netdev_priv(dev);
1945 struct slsi_dev *sdev = ndev_vif->sdev;
1946 int mode;
1947 int cur_pos = 0;
1948 int status;
1949 u8 alpha2[3];
1950 struct slsi_supported_channels supported_channels[5];
1951 int supp_chan_length;
1952
1953 mode = buf[strlen(CMD_GETREGULATORY) + 1] - '0';
1954 if (mode == 1) {
1955 struct slsi_802_11d_reg_domain domain_info;
1956
1957 memset(&domain_info, 0, sizeof(struct slsi_802_11d_reg_domain));
1958 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
1959 if (!ndev_vif->activated || ndev_vif->vif_type != FAPI_VIFTYPE_STATION || !ndev_vif->sta.sta_bss) {
1960 cur_pos += snprintf(buf, buf_len - cur_pos, "Station not connected");
1961 SLSI_ERR(sdev, "station not connected. vif.activated:%d, vif.type:%d, vif.bss:%s\n",
1962 ndev_vif->activated, ndev_vif->vif_type, ndev_vif->sta.sta_bss ? "yes" : "no");
1963 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1964 return -EINVAL;
1965 }
1966 /* read vif specific country code, index = vifid+1 */
1967 status = slsi_read_default_country(sdev, alpha2, ndev_vif->ifnum + 1);
1968 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
1969 if (status)
1970 return status;
1971
1972 /* max 20 rules */
1973 domain_info.regdomain = kmalloc(sizeof(*domain_info.regdomain) + sizeof(struct ieee80211_reg_rule) * 20, GFP_KERNEL);
1974 if (!domain_info.regdomain) {
1975 SLSI_ERR(sdev, "no memory size:%lu\n",
1976 sizeof(struct ieee80211_regdomain) + sizeof(struct ieee80211_reg_rule) * 20);
1977 return -ENOMEM;
1978 }
1979
1980 /* get regulatory rules based on country code */
1981 domain_info.countrylist = sdev->device_config.domain_info.countrylist;
1982 domain_info.country_len = sdev->device_config.domain_info.country_len;
1983 status = slsi_read_regulatory_rules(sdev, &domain_info, alpha2);
1984 if (status) {
1985 kfree(domain_info.regdomain);
1986 return status;
1987 }
1988 /* get supported channels based on country code */
1989 supp_chan_length = slsi_get_supported_channels(sdev, dev, &supported_channels[0]);
1990 cur_pos += slsi_print_regulatory(&domain_info, buf + cur_pos, buf_len - cur_pos, &supported_channels[0], supp_chan_length);
1991 kfree(domain_info.regdomain);
1992 } else if (mode == 0) {
1993 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
1994 supp_chan_length = slsi_get_supported_channels(sdev, dev, &supported_channels[0]);
1995 cur_pos += slsi_print_regulatory(&sdev->device_config.domain_info, buf + cur_pos, buf_len - cur_pos, &supported_channels[0], supp_chan_length);
1996 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
1997 } else {
1998 cur_pos += snprintf(buf, buf_len - cur_pos, "invalid option %d", mode);
1999 SLSI_ERR(sdev, "invalid option:%d\n", mode);
2000 return -EINVAL;
2001 }
2002 /* Buf is somewhere close to 4Kbytes. so expect some spare space. If there is no spare
2003 * space we might have missed printing some text in buf.
2004 */
2005 if (buf_len - cur_pos)
2006 return cur_pos;
2007 else
2008 return -ENOMEM;
2009}
2010
2011void slsi_disable_ch12_13(struct slsi_dev *sdev)
2012{
2013 struct wiphy *wiphy = sdev->wiphy;
2014 struct ieee80211_channel *chan;
2015
2016 if (wiphy->bands[0]) {
2017 chan = &wiphy->bands[0]->channels[11];
2018 chan->flags |= IEEE80211_CHAN_DISABLED;
2019 chan = &wiphy->bands[0]->channels[12];
2020 chan->flags |= IEEE80211_CHAN_DISABLED;
2021 }
2022
2023 SLSI_DBG1(sdev, SLSI_CFG80211, "Channels 12 and 13 have been disabled");
2024}
2025
2026int slsi_set_fcc_channel(struct net_device *dev, char *cmd, int cmd_len)
2027{
2028 struct netdev_vif *ndev_vif = netdev_priv(dev);
2029 struct slsi_dev *sdev = ndev_vif->sdev;
2030 int status;
2031 bool flight_mode_ena;
2032 u8 host_state;
2033 int err;
2034 char alpha2[3];
2035
2036 /* SET_FCC_CHANNEL 0 when device is in flightmode */
2037 flight_mode_ena = (cmd[0] == '0');
2038 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
2039 host_state = sdev->device_config.host_state;
2040
2041 if (flight_mode_ena)
2042 host_state = host_state & ~SLSI_HOSTSTATE_CELLULAR_ACTIVE;
2043 else
2044 host_state = host_state | SLSI_HOSTSTATE_CELLULAR_ACTIVE;
2045 sdev->device_config.host_state = host_state;
2046
2047 status = slsi_mlme_set_host_state(sdev, dev, host_state);
2048 if (status) {
2049 SLSI_ERR(sdev, "Err setting MMaxPowerEna. error = %d\n", status);
2050 } else {
2051 err = slsi_read_default_country(sdev, alpha2, 1);
2052 if (err) {
2053 SLSI_WARN(sdev, "Err updating reg_rules = %d\n", err);
2054 } else {
2055 memcpy(sdev->device_config.domain_info.regdomain->alpha2, alpha2, 2);
2056 /* Read the regulatory params for the country.*/
2057 if (slsi_read_regulatory_rules(sdev, &sdev->device_config.domain_info, alpha2) == 0) {
2058 slsi_reset_channel_flags(sdev);
2059 wiphy_apply_custom_regulatory(sdev->wiphy, sdev->device_config.domain_info.regdomain);
2060 slsi_update_supported_channels_regd_flags(sdev);
2061 if (flight_mode_ena && sdev->device_config.disable_ch12_ch13)
2062 slsi_disable_ch12_13(sdev);
2063 }
2064 }
2065 }
2066 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
2067
2068 return status;
2069}
2070
2071int slsi_fake_mac_write(struct net_device *dev, char *cmd)
2072{
2073 struct netdev_vif *ndev_vif = netdev_priv(dev);
2074 struct slsi_dev *sdev = ndev_vif->sdev;
2075 struct slsi_mib_data mib_data = { 0, NULL };
2076 int status;
2077 bool enable;
2078
2079 if (strncmp(cmd, "ON", strlen("ON")) == 0)
2080 enable = 1;
2081 else
2082 enable = 0;
2083
2084 status = slsi_mib_encode_bool(&mib_data, SLSI_PSID_UNIFI_MAC_ADDRESS_RANDOMISATION, enable, 0);
2085 if (status != SLSI_MIB_STATUS_SUCCESS) {
2086 SLSI_ERR(sdev, "FAKE MAC FAIL: no mem for MIB\n");
2087 return -ENOMEM;
2088 }
2089
2090 status = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength);
2091
2092 kfree(mib_data.data);
2093
2094 if (status)
2095 SLSI_ERR(sdev, "Err setting unifiMacAddrRandomistaion MIB. error = %d\n", status);
2096
2097 return status;
2098}
2099
2100static char *slsi_get_assoc_status(u16 fw_result_code)
2101{
2102 char *assoc_status_label = "unspecified_failure";
2103
2104 switch (fw_result_code) {
2105 case FAPI_RESULTCODE_SUCCESS:
2106 assoc_status_label = "success";
2107 break;
2108 case FAPI_RESULTCODE_TRANSMISSION_FAILURE:
2109 assoc_status_label = "transmission_failure";
2110 break;
2111 case FAPI_RESULTCODE_HOST_REQUEST_SUCCESS:
2112 assoc_status_label = "host_request_success";
2113 break;
2114 case FAPI_RESULTCODE_HOST_REQUEST_FAILED:
2115 assoc_status_label = "host_request_failed";
2116 break;
2117 case FAPI_RESULTCODE_PROBE_TIMEOUT:
2118 assoc_status_label = "probe_timeout";
2119 break;
2120 case FAPI_RESULTCODE_AUTH_TIMEOUT:
2121 assoc_status_label = "auth_timeout";
2122 break;
2123 case FAPI_RESULTCODE_ASSOC_TIMEOUT:
2124 assoc_status_label = "assoc_timeout";
2125 break;
2126 case FAPI_RESULTCODE_ASSOC_ABORT:
2127 assoc_status_label = "assoc_abort";
2128 break;
2129 }
2130 return assoc_status_label;
2131}
2132
2133int slsi_get_sta_info(struct net_device *dev, char *command, int buf_len)
2134{
2135 struct netdev_vif *ndev_vif = netdev_priv(dev);
2136 struct slsi_dev *sdev = ndev_vif->sdev;
2137 int len;
2138#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING
2139 struct net_device *ap_dev;
2140 struct netdev_vif *ndev_ap_vif;
2141
2142 ap_dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN);
2143
2144 if (ap_dev) {
2145 ndev_ap_vif = netdev_priv(ap_dev);
2146 SLSI_MUTEX_LOCK(ndev_ap_vif->vif_mutex);
2147 if (SLSI_IS_VIF_INDEX_MHS(sdev, ndev_ap_vif))
2148 ndev_vif = ndev_ap_vif;
2149 SLSI_MUTEX_UNLOCK(ndev_ap_vif->vif_mutex);
2150 }
2151#endif
2152
2153 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
2154
2155 if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_AP)) {
2156 SLSI_ERR(sdev, "slsi_get_sta_info: AP is not up.Command not allowed vif.activated:%d, vif.type:%d\n",
2157 ndev_vif->activated, ndev_vif->vif_type);
2158 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2159 return -EINVAL;
2160 }
2161
2162#if defined(ANDROID_VERSION) && (ANDROID_VERSION >= 90000)
2163 len = snprintf(command, buf_len, "GETSTAINFO %pM Rx_Retry_Pkts=%d Rx_BcMc_Pkts=%d CAP=%04x %02x:%02x:%02x ",
2164 ndev_vif->ap.last_disconnected_sta.address,
2165 ndev_vif->ap.last_disconnected_sta.rx_retry_packets,
2166 ndev_vif->ap.last_disconnected_sta.rx_bc_mc_packets,
2167 ndev_vif->ap.last_disconnected_sta.capabilities,
2168 ndev_vif->ap.last_disconnected_sta.address[0],
2169 ndev_vif->ap.last_disconnected_sta.address[1],
2170 ndev_vif->ap.last_disconnected_sta.address[2]);
2171
2172 len += snprintf(&command[len], (buf_len - len), "%d %d %d %d %d %d %d %u %d",
2173 ieee80211_frequency_to_channel(ndev_vif->ap.channel_freq),
2174 ndev_vif->ap.last_disconnected_sta.bandwidth, ndev_vif->ap.last_disconnected_sta.rssi,
2175 ndev_vif->ap.last_disconnected_sta.tx_data_rate, ndev_vif->ap.last_disconnected_sta.mode,
2176 ndev_vif->ap.last_disconnected_sta.antenna_mode,
2177 ndev_vif->ap.last_disconnected_sta.mimo_used, ndev_vif->ap.last_disconnected_sta.reason,
2178 ndev_vif->ap.last_disconnected_sta.support_mode);
2179#else
2180 len = snprintf(command, buf_len, "wl_get_sta_info : %02x%02x%02x %u %d %d %d %d %d %d %u ",
2181 ndev_vif->ap.last_disconnected_sta.address[0], ndev_vif->ap.last_disconnected_sta.address[1],
2182 ndev_vif->ap.last_disconnected_sta.address[2], ndev_vif->ap.channel_freq,
2183 ndev_vif->ap.last_disconnected_sta.bandwidth, ndev_vif->ap.last_disconnected_sta.rssi,
2184 ndev_vif->ap.last_disconnected_sta.tx_data_rate, ndev_vif->ap.last_disconnected_sta.mode,
2185 ndev_vif->ap.last_disconnected_sta.antenna_mode,
2186 ndev_vif->ap.last_disconnected_sta.mimo_used, ndev_vif->ap.last_disconnected_sta.reason);
2187#endif
2188
2189 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2190
2191 return len;
2192}
2193
2194static int slsi_get_bss_rssi(struct net_device *dev, char *command, int buf_len)
2195{
2196 struct netdev_vif *ndev_vif = netdev_priv(dev);
2197 int len = 0;
2198
2199 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
2200 len = snprintf(command, buf_len, "%d", ndev_vif->sta.last_connected_bss.rssi);
2201 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2202
2203 return len;
2204}
2205
2206static int slsi_get_bss_info(struct net_device *dev, char *command, int buf_len)
2207{
2208 struct netdev_vif *ndev_vif = netdev_priv(dev);
2209 int len = 0;
2210
2211 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
2212
2213 len = snprintf(command, buf_len, "%02x:%02x:%02x %u %u %d %u %u %u %u %u %d %d %u %u %u %u",
2214 ndev_vif->sta.last_connected_bss.address[0], ndev_vif->sta.last_connected_bss.address[1],
2215 ndev_vif->sta.last_connected_bss.address[2],
2216 ndev_vif->sta.last_connected_bss.channel_freq, ndev_vif->sta.last_connected_bss.bandwidth,
2217 ndev_vif->sta.last_connected_bss.rssi, ndev_vif->sta.last_connected_bss.tx_data_rate,
2218 ndev_vif->sta.last_connected_bss.mode, ndev_vif->sta.last_connected_bss.antenna_mode,
2219 ndev_vif->sta.last_connected_bss.mimo_used,
2220 ndev_vif->sta.last_connected_bss.passpoint_version, ndev_vif->sta.last_connected_bss.snr,
2221 ndev_vif->sta.last_connected_bss.noise_level, ndev_vif->sta.last_connected_bss.roaming_akm,
2222 ndev_vif->sta.last_connected_bss.roaming_count, ndev_vif->sta.last_connected_bss.kv,
2223 ndev_vif->sta.last_connected_bss.kvie);
2224
2225 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2226
2227 return len;
2228}
2229
2230static int slsi_get_linkspeed(struct net_device *dev, char *command, int buf_len)
2231{
2232 struct netdev_vif *ndev_vif = netdev_priv(dev);
2233 struct slsi_dev *sdev = ndev_vif->sdev;
2234 int len = 0;
2235
2236 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
2237 if (!ndev_vif->activated) {
2238 SLSI_ERR(sdev, "Not Activated, Command not allowed vif.activated:%d, vif.type:%d\n",
2239 ndev_vif->activated, ndev_vif->vif_type);
2240 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2241 return -EINVAL;
2242 }
2243
2244 if ((ndev_vif->vif_type != FAPI_VIFTYPE_STATION) && (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) {
2245 SLSI_NET_ERR(dev, "sta is not in connected state\n");
2246 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2247 return -EPERM;
2248 }
2249
2250 len = snprintf(command, buf_len, "MAX_SPEED %u CURRENT_LINK_SPEED %u",
2251 ndev_vif->sta.max_rate_mbps, ndev_vif->sta.data_rate_mbps);
2252
2253 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2254
2255 return len;
2256}
2257
2258static int slsi_get_assoc_reject_info(struct net_device *dev, char *command, int buf_len)
2259{
2260 struct netdev_vif *ndev_vif = netdev_priv(dev);
2261 struct slsi_dev *sdev = ndev_vif->sdev;
2262 int len = 0;
2263
2264 len = snprintf(command, buf_len, "assoc_reject.status : %d %s", sdev->assoc_result_code,
2265 slsi_get_assoc_status(sdev->assoc_result_code));
2266
2267 return len;
2268}
2269
2270#ifdef CONFIG_SCSC_WLAN_LOW_LATENCY_MODE
2271static int slsi_set_power_mode(struct net_device *dev, char *command, int buf_len)
2272{
2273 struct netdev_vif *ndev_vif = netdev_priv(dev);
2274 struct slsi_dev *sdev = ndev_vif->sdev;
2275 int status;
2276 u16 power_mode;
2277
2278 power_mode = (command[0] == '0') ? FAPI_POWERMANAGEMENTMODE_ACTIVE_MODE : FAPI_POWERMANAGEMENTMODE_POWER_SAVE;
2279 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
2280 if ((!ndev_vif->activated) || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) ||
2281 !(ndev_vif->sta.vif_status == SLSI_VIF_STATUS_CONNECTED)) {
2282 SLSI_ERR(sdev, "Command not allowed vif.activated:%d, vif.type:%d, ndev_vif->sta.vif_status:%d\n",
2283 ndev_vif->activated, ndev_vif->vif_type, ndev_vif->sta.vif_status);
2284 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2285 return -EINVAL;
2286 }
2287 status = slsi_mlme_powermgt(sdev, dev, power_mode);
2288 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2289
2290 return status;
2291}
2292#endif
2293
2294int slsi_set_disconnect_ies(struct net_device *dev, char *cmd, int cmd_len)
2295{
2296 struct netdev_vif *ndev_vif = netdev_priv(dev);
2297 struct slsi_dev *sdev = ndev_vif->sdev;
2298 char *disconnect_ies = cmd + strlen(CMD_SET_DISCONNECT_IES) + 1;
2299 int ie_len = 0;
2300 u8 *disconnect_ies_bin;
2301 u8 temp_byte;
2302 int i;
2303 int j;
2304 int len;
2305
2306 SLSI_DBG1(sdev, SLSI_CFG80211, "Setting disconnect IE's\n");
2307 while (disconnect_ies[ie_len])
2308 ie_len++;
2309
2310 /* ie_len has been trimmed to even, as odd length would mean that ie is invalid */
2311 ie_len &= (~0x01);
2312 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
2313 ndev_vif->sta.vendor_disconnect_ies_len = (ie_len / 2);
2314 disconnect_ies_bin = kmalloc(ndev_vif->sta.vendor_disconnect_ies_len, GFP_KERNEL);
2315 if (!disconnect_ies_bin) {
2316 SLSI_ERR(sdev, "Malloc failed\n");
2317 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2318 return -ENOMEM;
2319 }
2320
2321 for (i = 0, j = 0; j < ie_len; j += 2) {
2322 temp_byte = slsi_parse_hex(disconnect_ies[j]) << 4 | slsi_parse_hex(disconnect_ies[j + 1]);
2323 disconnect_ies_bin[i++] = temp_byte;
2324 }
2325
2326 /* check if the IE is valid */
2327 for (i = 0; i < ndev_vif->sta.vendor_disconnect_ies_len;) {
2328 if (disconnect_ies_bin[i] == 0xdd) {
2329 len = disconnect_ies_bin[i + 1];
2330 if ((ndev_vif->sta.vendor_disconnect_ies_len - (i + 2)) < len) {
2331 SLSI_WARN(sdev, "The length of disconnect IE's is not proper\n");
2332 ndev_vif->sta.vendor_disconnect_ies_len = 0;
2333 kfree(disconnect_ies_bin);
2334 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2335 return -EINVAL;
2336 }
2337
2338 i = i + 2 + len;
2339 } else {
2340 SLSI_WARN(sdev, "The tag of disconnect IE's is not proper\n");
2341 ndev_vif->sta.vendor_disconnect_ies_len = 0;
2342 kfree(disconnect_ies_bin);
2343 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2344 return -EINVAL;
2345 }
2346 }
2347 ndev_vif->sta.vendor_disconnect_ies = disconnect_ies_bin;
2348 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2349
2350 return 0;
2351}
2352
2353#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
2354static int slsi_enhanced_arp_start_stop(struct net_device *dev, char *command, int buf_len)
2355{
2356 struct netdev_vif *ndev_vif = netdev_priv(dev);
2357 struct slsi_dev *sdev = ndev_vif->sdev;
2358 int result = 0;
2359 int readbyte = 0;
2360 int readvalue = 0;
2361 int i = 0;
2362
2363 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
2364 if (!sdev->device_config.fw_enhanced_arp_detect_supported) {
2365 SLSI_ERR(sdev, "Enhanced ARP Detect Feature is not supported.\n");
2366 return -ENOTSUPP;
2367 }
2368 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
2369
2370 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
2371 if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) {
2372 SLSI_ERR(sdev, "Not in STA mode\n");
2373 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex)
2374 return -EPERM;
2375 }
2376
2377 SLSI_DBG1(sdev, SLSI_CFG80211, "Enhanced ARP Start/Stop\n");
2378
2379 for (i = 0; i < 4 ; i++) {
2380 readbyte = slsi_str_to_int(command, &readvalue);
2381 ndev_vif->target_ip_addr[i] = readvalue;
2382 command = command + readbyte + 1;
2383 }
2384
2385 if (ndev_vif->target_ip_addr[0] != 0) { /* start enhanced arp detect */
2386 /* clear all the counters */
2387 memset(&ndev_vif->enhanced_arp_stats, 0, sizeof(ndev_vif->enhanced_arp_stats));
2388 ndev_vif->enhanced_arp_detect_enabled = true;
2389 result = slsi_mlme_arp_detect_request(sdev, dev, FAPI_ACTION_START, ndev_vif->target_ip_addr);
2390 } else { /* stop enhanced arp detect */
2391 ndev_vif->enhanced_arp_detect_enabled = false;
2392 result = slsi_mlme_arp_detect_request(sdev, dev, FAPI_ACTION_STOP, ndev_vif->target_ip_addr);
2393 }
2394
2395 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2396 return result;
2397}
2398
2399static int slsi_enhanced_arp_get_stats(struct net_device *dev, char *command, int buf_len)
2400{
2401 struct netdev_vif *ndev_vif = netdev_priv(dev);
2402 struct slsi_dev *sdev = ndev_vif->sdev;
2403 int r = 0;
2404 int len = 0;
2405
2406 r = slsi_read_enhanced_arp_rx_count_by_lower_mac(sdev, dev, SLSI_PSID_UNIFI_ARP_DETECT_RESPONSE_COUNTER);
2407
2408 if (r == 0) {
2409 len = snprintf(command, buf_len, "%d %d %d %d %d %d %d %d %d %d",
2410 ndev_vif->enhanced_arp_stats.arp_req_count_from_netdev,
2411 ndev_vif->enhanced_arp_stats.arp_req_count_to_lower_mac,
2412 ndev_vif->enhanced_arp_stats.arp_req_rx_count_by_lower_mac,
2413 ndev_vif->enhanced_arp_stats.arp_req_count_tx_success,
2414 ndev_vif->enhanced_arp_stats.arp_rsp_rx_count_by_lower_mac,
2415 ndev_vif->enhanced_arp_stats.arp_rsp_rx_count_by_upper_mac,
2416 ndev_vif->enhanced_arp_stats.arp_rsp_count_to_netdev,
2417 ndev_vif->enhanced_arp_stats.arp_rsp_count_out_of_order_drop,
2418 0, /*ap_link_active not supported, set as 0*/
2419 ndev_vif->enhanced_arp_stats.is_duplicate_addr_detected);
2420 }
2421
2422 /*clear all the counters*/
2423 memset(&ndev_vif->enhanced_arp_stats, 0, sizeof(ndev_vif->enhanced_arp_stats));
2424
2425 return len;
2426}
2427#endif
2428
2429int slsi_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2430{
2431#define MAX_LEN_PRIV_COMMAND 4096 /*This value is the max reply size set in supplicant*/
2432 struct android_wifi_priv_cmd priv_cmd;
2433 int ret = 0;
2434 u8 *command = NULL;
2435
2436 if (!dev) {
2437 ret = -ENODEV;
2438 goto exit;
2439 }
2440
2441 if (!rq->ifr_data) {
2442 ret = -EINVAL;
2443 goto exit;
2444 }
2445 if (copy_from_user((void *)&priv_cmd, (void *)rq->ifr_data, sizeof(struct android_wifi_priv_cmd))) {
2446 ret = -EFAULT;
2447 SLSI_NET_ERR(dev, "ifr data failed\n");
2448 goto exit;
2449 }
2450
2451 if ((priv_cmd.total_len > MAX_LEN_PRIV_COMMAND) || (priv_cmd.total_len < 0)) {
2452 ret = -EINVAL;
2453 SLSI_NET_ERR(dev, "Length mismatch total_len = %d\n", priv_cmd.total_len);
2454 goto exit;
2455 }
2456 command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL);
2457 if (!command) {
2458 ret = -ENOMEM;
2459 SLSI_NET_ERR(dev, "No memory\n");
2460 goto exit;
2461 }
2462 if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
2463 ret = -EFAULT;
2464 SLSI_NET_ERR(dev, "Buffer copy fail\n");
2465 goto exit;
2466 }
2467 command[priv_cmd.total_len] = '\0';
2468
2469 SLSI_INFO_NODEV("command: %.*s\n", priv_cmd.total_len, command);
2470
2471 if (strncasecmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) {
2472 ret = slsi_set_suspend_mode(dev, command);
2473 } else if (strncasecmp(command, CMD_SETJOINPREFER, strlen(CMD_SETJOINPREFER)) == 0) {
2474 char *rssi_boost_string = command + strlen(CMD_SETJOINPREFER) + 1;
2475
2476 ret = slsi_update_rssi_boost(dev, rssi_boost_string);
2477 } else if (strncasecmp(command, CMD_RXFILTERADD, strlen(CMD_RXFILTERADD)) == 0) {
2478 int filter_num = *(command + strlen(CMD_RXFILTERADD) + 1) - '0';
2479
2480 ret = slsi_rx_filter_num_write(dev, 1, filter_num);
2481 } else if (strncasecmp(command, CMD_RXFILTERREMOVE, strlen(CMD_RXFILTERREMOVE)) == 0) {
2482 int filter_num = *(command + strlen(CMD_RXFILTERREMOVE) + 1) - '0';
2483
2484 ret = slsi_rx_filter_num_write(dev, 0, filter_num);
2485#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING
2486#if !defined(CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE) || (defined(ANDROID_VERSION) && ANDROID_VERSION < 90000)
2487 } else if (strncasecmp(command, CMD_INTERFACE_CREATE, strlen(CMD_INTERFACE_CREATE)) == 0) {
2488 char *intf_name = command + strlen(CMD_INTERFACE_CREATE) + 1;
2489
2490 ret = slsi_create_interface(dev, intf_name);
2491 } else if (strncasecmp(command, CMD_INTERFACE_DELETE, strlen(CMD_INTERFACE_DELETE)) == 0) {
2492 char *intf_name = command + strlen(CMD_INTERFACE_DELETE) + 1;
2493
2494 ret = slsi_delete_interface(dev, intf_name);
2495#endif
2496 } else if (strncasecmp(command, CMD_SET_INDOOR_CHANNELS, strlen(CMD_SET_INDOOR_CHANNELS)) == 0) {
2497 char *arg = command + strlen(CMD_SET_INDOOR_CHANNELS) + 1;
2498
2499 ret = slsi_set_indoor_channels(dev, arg);
2500 } else if (strncasecmp(command, CMD_GET_INDOOR_CHANNELS, strlen(CMD_GET_INDOOR_CHANNELS)) == 0) {
2501 ret = slsi_get_indoor_channels(dev, command, priv_cmd.total_len);
2502#endif
2503 } else if (strncasecmp(command, CMD_SETCOUNTRYREV, strlen(CMD_SETCOUNTRYREV)) == 0) {
2504 char *country_code = command + strlen(CMD_SETCOUNTRYREV) + 1;
2505
2506 ret = slsi_set_country_rev(dev, country_code);
2507 } else if (strncasecmp(command, CMD_GETCOUNTRYREV, strlen(CMD_GETCOUNTRYREV)) == 0) {
2508 ret = slsi_get_country_rev(dev, command, priv_cmd.total_len);
2509#ifdef CONFIG_SCSC_WLAN_WES_NCHO
2510 } else if (strncasecmp(command, CMD_SETROAMTRIGGER, strlen(CMD_SETROAMTRIGGER)) == 0) {
2511 int skip = strlen(CMD_SETROAMTRIGGER) + 1;
2512
2513 ret = slsi_roam_scan_trigger_write(dev, command + skip,
2514 priv_cmd.total_len - skip);
2515 } else if (strncasecmp(command, CMD_GETROAMTRIGGER, strlen(CMD_GETROAMTRIGGER)) == 0) {
2516 ret = slsi_roam_scan_trigger_read(dev, command, priv_cmd.total_len);
2517 } else if (strncasecmp(command, CMD_SETROAMDELTA, strlen(CMD_SETROAMDELTA)) == 0) {
2518 int skip = strlen(CMD_SETROAMDELTA) + 1;
2519
2520 ret = slsi_roam_delta_trigger_write(dev, command + skip,
2521 priv_cmd.total_len - skip);
2522 } else if (strncasecmp(command, CMD_GETROAMDELTA, strlen(CMD_GETROAMDELTA)) == 0) {
2523 ret = slsi_roam_delta_trigger_read(dev, command, priv_cmd.total_len);
2524 } else if (strncasecmp(command, CMD_SETROAMSCANPERIOD, strlen(CMD_SETROAMSCANPERIOD)) == 0) {
2525 int skip = strlen(CMD_SETROAMSCANPERIOD) + 1;
2526
2527 ret = slsi_cached_channel_scan_period_write(dev, command + skip,
2528 priv_cmd.total_len - skip);
2529 } else if (strncasecmp(command, CMD_GETROAMSCANPERIOD, strlen(CMD_GETROAMSCANPERIOD)) == 0) {
2530 ret = slsi_cached_channel_scan_period_read(dev, command, priv_cmd.total_len);
2531 } else if (strncasecmp(command, CMD_SETFULLROAMSCANPERIOD, strlen(CMD_SETFULLROAMSCANPERIOD)) == 0) {
2532 int skip = strlen(CMD_SETFULLROAMSCANPERIOD) + 1;
2533
2534 ret = slsi_full_roam_scan_period_write(dev, command + skip,
2535 priv_cmd.total_len - skip);
2536 } else if (strncasecmp(command, CMD_GETFULLROAMSCANPERIOD, strlen(CMD_GETFULLROAMSCANPERIOD)) == 0) {
2537 ret = slsi_full_roam_scan_period_read(dev, command, priv_cmd.total_len);
2538 } else if (strncasecmp(command, CMD_SETSCANCHANNELTIME, strlen(CMD_SETSCANCHANNELTIME)) == 0) {
2539 int skip = strlen(CMD_SETSCANCHANNELTIME) + 1;
2540
2541 ret = slsi_roam_scan_max_active_channel_time_write(dev, command + skip,
2542 priv_cmd.total_len - skip);
2543 } else if (strncasecmp(command, CMD_GETSCANCHANNELTIME, strlen(CMD_GETSCANCHANNELTIME)) == 0) {
2544 ret = slsi_roam_scan_max_active_channel_time_read(dev, command, priv_cmd.total_len);
2545 } else if (strncasecmp(command, CMD_SETSCANNPROBES, strlen(CMD_SETSCANNPROBES)) == 0) {
2546 int skip = strlen(CMD_SETSCANNPROBES) + 1;
2547
2548 ret = slsi_roam_scan_probe_interval_write(dev, command + skip,
2549 priv_cmd.total_len - skip);
2550 } else if (strncasecmp(command, CMD_GETSCANNPROBES, strlen(CMD_GETSCANNPROBES)) == 0) {
2551 ret = slsi_roam_scan_probe_interval_read(dev, command, priv_cmd.total_len);
2552 } else if (strncasecmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0) {
2553 int skip = strlen(CMD_SETROAMMODE) + 1;
2554
2555 ret = slsi_roam_mode_write(dev, command + skip,
2556 priv_cmd.total_len - skip);
2557 } else if (strncasecmp(command, CMD_GETROAMMODE, strlen(CMD_GETROAMMODE)) == 0) {
2558 ret = slsi_roam_mode_read(dev, command, priv_cmd.total_len);
2559 } else if (strncasecmp(command, CMD_SETROAMINTRABAND, strlen(CMD_SETROAMINTRABAND)) == 0) {
2560 int skip = strlen(CMD_SETROAMINTRABAND) + 1;
2561
2562 ret = slsi_roam_scan_band_write(dev, command + skip,
2563 priv_cmd.total_len - skip);
2564 } else if (strncasecmp(command, CMD_GETROAMINTRABAND, strlen(CMD_GETROAMINTRABAND)) == 0) {
2565 ret = slsi_roam_scan_band_read(dev, command, priv_cmd.total_len);
2566 } else if (strncasecmp(command, CMD_SETROAMBAND, strlen(CMD_SETROAMBAND)) == 0) {
2567 uint band = *(command + strlen(CMD_SETROAMBAND) + 1) - '0';
2568
2569 ret = slsi_freq_band_write(dev, band);
2570 } else if (strncasecmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
2571 uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
2572
2573 ret = slsi_freq_band_write(dev, band);
2574 } else if ((strncasecmp(command, CMD_GETROAMBAND, strlen(CMD_GETROAMBAND)) == 0) || (strncasecmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0)) {
2575 ret = slsi_freq_band_read(dev, command, priv_cmd.total_len);
2576 } else if (strncasecmp(command, CMD_SETROAMSCANCONTROL, strlen(CMD_SETROAMSCANCONTROL)) == 0) {
2577 int mode = *(command + strlen(CMD_SETROAMSCANCONTROL) + 1) - '0';
2578
2579 ret = slsi_roam_scan_control_write(dev, mode);
2580 } else if (strncasecmp(command, CMD_GETROAMSCANCONTROL, strlen(CMD_GETROAMSCANCONTROL)) == 0) {
2581 ret = slsi_roam_scan_control_read(dev, command, priv_cmd.total_len);
2582 } else if (strncasecmp(command, CMD_SETSCANHOMETIME, strlen(CMD_SETSCANHOMETIME)) == 0) {
2583 int skip = strlen(CMD_SETSCANHOMETIME) + 1;
2584
2585 ret = slsi_roam_scan_home_time_write(dev, command + skip,
2586 priv_cmd.total_len - skip);
2587 } else if (strncasecmp(command, CMD_GETSCANHOMETIME, strlen(CMD_GETSCANHOMETIME)) == 0) {
2588 ret = slsi_roam_scan_home_time_read(dev, command, priv_cmd.total_len);
2589 } else if (strncasecmp(command, CMD_SETSCANHOMEAWAYTIME, strlen(CMD_SETSCANHOMEAWAYTIME)) == 0) {
2590 int skip = strlen(CMD_SETSCANHOMEAWAYTIME) + 1;
2591
2592 ret = slsi_roam_scan_home_away_time_write(dev, command + skip,
2593 priv_cmd.total_len - skip);
2594 } else if (strncasecmp(command, CMD_GETSCANHOMEAWAYTIME, strlen(CMD_GETSCANHOMEAWAYTIME)) == 0) {
2595 ret = slsi_roam_scan_home_away_time_read(dev, command, priv_cmd.total_len);
2596 } else if (strncasecmp(command, CMD_SETOKCMODE, strlen(CMD_SETOKCMODE)) == 0) {
2597 int mode = *(command + strlen(CMD_SETOKCMODE) + 1) - '0';
2598
2599 ret = slsi_okc_mode_write(dev, mode);
2600 } else if (strncasecmp(command, CMD_GETOKCMODE, strlen(CMD_GETOKCMODE)) == 0) {
2601 ret = slsi_okc_mode_read(dev, command, priv_cmd.total_len);
2602 } else if (strncasecmp(command, CMD_SETWESMODE, strlen(CMD_SETWESMODE)) == 0) {
2603 int mode = *(command + strlen(CMD_SETWESMODE) + 1) - '0';
2604
2605 ret = slsi_wes_mode_write(dev, mode);
2606 } else if (strncasecmp(command, CMD_GETWESMODE, strlen(CMD_GETWESMODE)) == 0) {
2607 ret = slsi_wes_mode_read(dev, command, priv_cmd.total_len);
2608 } else if (strncasecmp(command, CMD_SETROAMSCANCHANNELS, strlen(CMD_SETROAMSCANCHANNELS)) == 0) {
2609 int skip = strlen(CMD_SETROAMSCANCHANNELS) + 1;
2610
2611 ret = slsi_roam_scan_channels_write(dev, command + skip,
2612 priv_cmd.total_len - skip);
2613 } else if (strncasecmp(command, CMD_GETROAMSCANCHANNELS, strlen(CMD_GETROAMSCANCHANNELS)) == 0) {
2614 ret = slsi_roam_scan_channels_read(dev, command, priv_cmd.total_len);
2615#endif
2616 } else if (strncasecmp(command, CMD_SET_PMK, strlen(CMD_SET_PMK)) == 0) {
2617 ret = slsi_set_pmk(dev, command, priv_cmd.total_len);
2618 } else if (strncasecmp(command, CMD_HAPD_GET_CHANNEL, strlen(CMD_HAPD_GET_CHANNEL)) == 0) {
2619 ret = slsi_auto_chan_read(dev, command, priv_cmd.total_len);
2620 } else if (strncasecmp(command, CMD_SET_SAP_CHANNEL_LIST, strlen(CMD_SET_SAP_CHANNEL_LIST)) == 0) {
2621 int skip = strlen(CMD_SET_SAP_CHANNEL_LIST) + 1;
2622
2623 ret = slsi_auto_chan_write(dev, command + skip);
2624 } else if (strncasecmp(command, CMD_REASSOC, strlen(CMD_REASSOC)) == 0) {
2625 int skip = strlen(CMD_REASSOC) + 1;
2626
2627 ret = slsi_reassoc_write(dev, command + skip,
2628 priv_cmd.total_len - skip);
2629 } else if (strncasecmp(command, CMD_SENDACTIONFRAME, strlen(CMD_SENDACTIONFRAME)) == 0) {
2630 int skip = strlen(CMD_SENDACTIONFRAME) + 1;
2631
2632 ret = slsi_send_action_frame(dev, command + skip,
2633 priv_cmd.total_len - skip);
2634 } else if (strncasecmp(command, CMD_HAPD_MAX_NUM_STA, strlen(CMD_HAPD_MAX_NUM_STA)) == 0) {
2635 int sta_num;
2636 u8 *max_sta = command + strlen(CMD_HAPD_MAX_NUM_STA) + 1;
2637
2638 slsi_str_to_int(max_sta, &sta_num);
2639 ret = slsi_setting_max_sta_write(dev, sta_num);
2640 } else if (strncasecmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
2641 char *country_code = command + strlen(CMD_COUNTRY) + 1;
2642
2643 ret = slsi_country_write(dev, country_code);
2644#ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON
2645 } else if (strncasecmp(command, CMD_BEACON_RECV, strlen(CMD_BEACON_RECV)) == 0) {
2646 char *action = command + strlen(CMD_BEACON_RECV) + 1;
2647
2648 ret = slsi_forward_beacon(dev, action);
2649#endif
2650 } else if (strncasecmp(command, CMD_SETAPP2PWPSIE, strlen(CMD_SETAPP2PWPSIE)) == 0) {
2651 ret = slsi_set_ap_p2p_wps_ie(dev, command, priv_cmd.total_len);
2652 } else if (strncasecmp(command, CMD_P2PSETPS, strlen(CMD_P2PSETPS)) == 0) {
2653 ret = slsi_set_p2p_oppps(dev, command, priv_cmd.total_len);
2654 } else if (strncasecmp(command, CMD_P2PSETNOA, strlen(CMD_P2PSETNOA)) == 0) {
2655 ret = slsi_p2p_set_noa_params(dev, command, priv_cmd.total_len);
2656 } else if (strncasecmp(command, CMD_P2PECSA, strlen(CMD_P2PECSA)) == 0) {
2657 ret = slsi_p2p_ecsa(dev, command);
2658 } else if (strncasecmp(command, CMD_P2PLOSTART, strlen(CMD_P2PLOSTART)) == 0) {
2659 ret = slsi_p2p_lo_start(dev, command);
2660 } else if (strncasecmp(command, CMD_P2PLOSTOP, strlen(CMD_P2PLOSTOP)) == 0) {
2661 ret = slsi_p2p_lo_stop(dev);
2662 } else if (strncasecmp(command, CMD_SETROAMOFFLOAD, strlen(CMD_SETROAMOFFLOAD)) == 0) {
2663 ret = slsi_roam_mode_write(dev, command + strlen(CMD_SETROAMOFFLOAD) + 1,
2664 priv_cmd.total_len - (strlen(CMD_SETROAMOFFLOAD) + 1));
2665 } else if (strncasecmp(command, CMD_SETROAMOFFLAPLIST, strlen(CMD_SETROAMOFFLAPLIST)) == 0) {
2666 ret = slsi_roam_offload_ap_list(dev, command + strlen(CMD_SETROAMOFFLAPLIST) + 1,
2667 priv_cmd.total_len - (strlen(CMD_SETROAMOFFLAPLIST) + 1));
2668 } else if (strncasecmp(command, CMD_SET_TX_POWER_CALLING, strlen(CMD_SET_TX_POWER_CALLING)) == 0) {
2669 ret = slsi_set_tx_power_calling(dev, command + strlen(CMD_SET_TX_POWER_CALLING) + 1,
2670 priv_cmd.total_len - (strlen(CMD_SET_TX_POWER_CALLING) + 1));
2671 } else if (strncasecmp(command, CMD_SET_TX_POWER_SAR, strlen(CMD_SET_TX_POWER_SAR)) == 0) {
2672 ret = slsi_set_tx_power_sar(dev, command + strlen(CMD_SET_TX_POWER_SAR) + 1,
2673 priv_cmd.total_len - (strlen(CMD_SET_TX_POWER_SAR) + 1));
2674 } else if (strncasecmp(command, CMD_GET_TX_POWER_SAR, strlen(CMD_GET_TX_POWER_SAR)) == 0) {
2675 ret = slsi_get_tx_power_sar(dev, command, priv_cmd.total_len);
2676 } else if (strncasecmp(command, CMD_GETREGULATORY, strlen(CMD_GETREGULATORY)) == 0) {
2677 ret = slsi_get_regulatory(dev, command, priv_cmd.total_len);
2678#ifdef CONFIG_SCSC_WLAN_HANG_TEST
2679 } else if (strncasecmp(command, CMD_TESTFORCEHANG, strlen(CMD_TESTFORCEHANG)) == 0) {
2680 ret = slsi_test_send_hanged_vendor_event(dev);
2681#endif
2682 } else if (strncasecmp(command, CMD_SET_FCC_CHANNEL, strlen(CMD_SET_FCC_CHANNEL)) == 0) {
2683 ret = slsi_set_fcc_channel(dev, command + strlen(CMD_SET_FCC_CHANNEL) + 1,
2684 priv_cmd.total_len - (strlen(CMD_SET_FCC_CHANNEL) + 1));
2685 } else if (strncasecmp(command, CMD_FAKEMAC, strlen(CMD_FAKEMAC)) == 0) {
2686 ret = slsi_fake_mac_write(dev, command + strlen(CMD_FAKEMAC) + 1);
2687 } else if (strncasecmp(command, CMD_GETBSSRSSI, strlen(CMD_GETBSSRSSI)) == 0) {
2688 ret = slsi_get_bss_rssi(dev, command, priv_cmd.total_len);
2689 } else if (strncasecmp(command, CMD_GETBSSINFO, strlen(CMD_GETBSSINFO)) == 0) {
2690 ret = slsi_get_bss_info(dev, command, priv_cmd.total_len);
2691 } else if (strncasecmp(command, CMD_GETSTAINFO, strlen(CMD_GETSTAINFO)) == 0) {
2692 ret = slsi_get_sta_info(dev, command, priv_cmd.total_len);
2693 } else if (strncasecmp(command, CMD_GETASSOCREJECTINFO, strlen(CMD_GETASSOCREJECTINFO)) == 0) {
2694 ret = slsi_get_assoc_reject_info(dev, command, priv_cmd.total_len);
2695#ifdef CONFIG_SCSC_WLAN_LOW_LATENCY_MODE
2696 } else if (strncasecmp(command, CMD_SET_LATENCY_MODE, strlen(CMD_SET_LATENCY_MODE)) == 0) {
2697 int latency_mode = *(command + strlen(CMD_SET_LATENCY_MODE) + 1) - '0';
2698 int cmd_len = priv_cmd.total_len - (strlen(CMD_SET_LATENCY_MODE) + 1);
2699
2700 ret = slsi_set_latency_mode(dev, latency_mode, cmd_len);
2701 } else if (strncasecmp(command, CMD_SET_POWER_MGMT, strlen(CMD_SET_POWER_MGMT)) == 0) {
2702 ret = slsi_set_power_mode(dev, command + strlen(CMD_SET_POWER_MGMT) + 1,
2703 priv_cmd.total_len - (strlen(CMD_SET_POWER_MGMT) + 1));
2704#endif
2705 } else if (strncasecmp(command, CMD_SET_DISCONNECT_IES, strlen(CMD_SET_DISCONNECT_IES)) == 0) {
2706 ret = slsi_set_disconnect_ies(dev, command, priv_cmd.total_len);
2707#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
2708 } else if (strncasecmp(command, CMD_SET_ENHANCED_ARP_TARGET, strlen(CMD_SET_ENHANCED_ARP_TARGET)) == 0) {
2709 int skip = strlen(CMD_SET_ENHANCED_ARP_TARGET) + 1;
2710
2711 ret = slsi_enhanced_arp_start_stop(dev, command + skip, priv_cmd.total_len - skip);
2712 } else if (strncasecmp(command, CMD_GET_ENHANCED_ARP_COUNTS, strlen(CMD_SET_ENHANCED_ARP_TARGET)) == 0) {
2713 ret = slsi_enhanced_arp_get_stats(dev, command, priv_cmd.total_len);
2714#endif
2715 } else if ((strncasecmp(command, CMD_RXFILTERSTART, strlen(CMD_RXFILTERSTART)) == 0) ||
2716 (strncasecmp(command, CMD_RXFILTERSTOP, strlen(CMD_RXFILTERSTOP)) == 0) ||
2717 (strncasecmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) ||
2718 (strncasecmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) ||
2719 (strncasecmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) ||
2720 (strncasecmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0)) {
2721 ret = 0;
2722 } else if ((strncasecmp(command, CMD_AMPDU_MPDU, strlen(CMD_AMPDU_MPDU)) == 0) ||
2723 (strncasecmp(command, CMD_CHANGE_RL, strlen(CMD_CHANGE_RL)) == 0) ||
2724 (strncasecmp(command, CMD_INTERFACE_CREATE, strlen(CMD_INTERFACE_CREATE)) == 0) ||
2725 (strncasecmp(command, CMD_INTERFACE_DELETE, strlen(CMD_INTERFACE_DELETE)) == 0) ||
2726 (strncasecmp(command, CMD_LTECOEX, strlen(CMD_LTECOEX)) == 0) ||
2727 (strncasecmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0) ||
2728 (strncasecmp(command, CMD_RPSMODE, strlen(CMD_RPSMODE)) == 0) ||
2729 (strncasecmp(command, CMD_SETCCXMODE, strlen(CMD_SETCCXMODE)) == 0) ||
2730 (strncasecmp(command, CMD_SETDFSSCANMODE, strlen(CMD_SETDFSSCANMODE)) == 0) ||
2731 (strncasecmp(command, CMD_SETSINGLEANT, strlen(CMD_SETSINGLEANT)) == 0)) {
2732 ret = -ENOTSUPP;
2733#ifndef SLSI_TEST_DEV
2734 } else if ((strncasecmp(command, CMD_DRIVERDEBUGDUMP, strlen(CMD_DRIVERDEBUGDUMP)) == 0) ||
2735 (strncasecmp(command, CMD_DRIVERDEBUGCOMMAND, strlen(CMD_DRIVERDEBUGCOMMAND)) == 0)) {
2736 slsi_dump_stats(dev);
2737#ifdef CONFIG_SCSC_LOG_COLLECTION
2738 scsc_log_collector_schedule_collection(SCSC_LOG_DUMPSTATE, SCSC_LOG_DUMPSTATE_REASON_DRIVERDEBUGDUMP);
2739#else
2740 ret = mx140_log_dump();
2741#endif
2742#endif
2743#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
2744 } else if ((strncasecmp(command, CMD_ENHANCED_PKT_FILTER, strlen(CMD_ENHANCED_PKT_FILTER)) == 0)) {
2745 const u8 enable = *(command + strlen(CMD_ENHANCED_PKT_FILTER) + 1) - '0';
2746
2747 ret = slsi_set_enhanced_pkt_filter(dev, enable);
2748#endif
1f642a2e
Y
2749#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER
2750 } else if ((strncasecmp(command, CMD_ABNORMAL_MULTICAST_PKT_FILTER, strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER)) == 0)) {
2751 const u8 enable = *(command + strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER) + 1) - '0';
2752
2753 ret = slsi_set_abnormal_multicast_pkt_filter(dev, enable);
2754#endif
4dcd9de9
TK
2755#ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS
2756 } else if (strncasecmp(command, CMD_SET_NUM_ANTENNAS, strlen(CMD_SET_NUM_ANTENNAS)) == 0) {
2757 struct netdev_vif *ndev_vif = netdev_priv(dev);
2758 const u16 num_of_antennas = *(command + strlen(CMD_SET_NUM_ANTENNAS) + 1) - '0';
2759
2760 /* We cannot lock in slsi_set_num_antennas as
2761 * this is also called in slsi_start_ap with netdev_vif lock.
2762 */
2763 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
2764 ret = slsi_set_num_antennas(dev, num_of_antennas);
2765 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
2766#endif
2767 } else if ((strncasecmp(command, CMD_GET_MAX_LINK_SPEED, strlen(CMD_GET_MAX_LINK_SPEED)) == 0)) {
2768 ret = slsi_get_linkspeed(dev, command, priv_cmd.total_len);
2769 } else {
2770 ret = -ENOTSUPP;
2771 }
2772 if (strncasecmp(command, CMD_SETROAMBAND, strlen(CMD_SETROAMBAND)) != 0 && strncasecmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) != 0 && copy_to_user(priv_cmd.buf, command, priv_cmd.total_len)) {
2773 ret = -EFAULT;
2774 SLSI_NET_ERR(dev, "Buffer copy fail\n");
2775 }
2776
2777exit:
2778 kfree(command);
2779 return ret;
2780}