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