blob: 2c2e8aca8305d3f77f15b9d637b544dbd7c4ac83 [file] [log] [blame]
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001#include "wilc_wfi_cfgoperations.h"
Arnd Bergmann491880e2015-11-16 15:04:55 +01002#include "host_interface.h"
Leo Kim7ae43362015-09-16 18:35:59 +09003#include <linux/errno.h>
Johnny Kimc5c77ba2015-05-11 14:30:56 +09004
Arnd Bergmann15162fb2015-11-16 15:04:57 +01005#define NO_ENCRYPT 0
6#define ENCRYPT_ENABLED BIT(0)
7#define WEP BIT(1)
8#define WEP_EXTENDED BIT(2)
9#define WPA BIT(3)
10#define WPA2 BIT(4)
11#define AES BIT(5)
12#define TKIP BIT(6)
13
Arnd Bergmann15162fb2015-11-16 15:04:57 +010014#define FRAME_TYPE_ID 0
15#define ACTION_CAT_ID 24
16#define ACTION_SUBTYPE_ID 25
17#define P2P_PUB_ACTION_SUBTYPE 30
18
Arnd Bergmann15162fb2015-11-16 15:04:57 +010019#define ACTION_FRAME 0xd0
20#define GO_INTENT_ATTR_ID 0x04
21#define CHANLIST_ATTR_ID 0x0b
22#define OPERCHAN_ATTR_ID 0x11
23#define PUB_ACTION_ATTR_ID 0x04
24#define P2PELEM_ATTR_ID 0xdd
25
Arnd Bergmann15162fb2015-11-16 15:04:57 +010026#define GO_NEG_REQ 0x00
27#define GO_NEG_RSP 0x01
28#define GO_NEG_CONF 0x02
29#define P2P_INV_REQ 0x03
30#define P2P_INV_RSP 0x04
31#define PUBLIC_ACT_VENDORSPEC 0x09
32#define GAS_INTIAL_REQ 0x0a
33#define GAS_INTIAL_RSP 0x0b
34
35#define INVALID_CHANNEL 0
36
37#define nl80211_SCAN_RESULT_EXPIRE (3 * HZ)
38#define SCAN_RESULT_EXPIRE (40 * HZ)
39
40static const u32 cipher_suites[] = {
41 WLAN_CIPHER_SUITE_WEP40,
42 WLAN_CIPHER_SUITE_WEP104,
43 WLAN_CIPHER_SUITE_TKIP,
44 WLAN_CIPHER_SUITE_CCMP,
45 WLAN_CIPHER_SUITE_AES_CMAC,
46};
47
48static const struct ieee80211_txrx_stypes
49 wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = {
50 [NL80211_IFTYPE_STATION] = {
51 .tx = 0xffff,
52 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
53 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
54 },
55 [NL80211_IFTYPE_AP] = {
56 .tx = 0xffff,
57 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
58 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
59 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
60 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
61 BIT(IEEE80211_STYPE_AUTH >> 4) |
62 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
63 BIT(IEEE80211_STYPE_ACTION >> 4)
64 },
65 [NL80211_IFTYPE_P2P_CLIENT] = {
66 .tx = 0xffff,
67 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
68 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
69 BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
70 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
71 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
72 BIT(IEEE80211_STYPE_AUTH >> 4) |
73 BIT(IEEE80211_STYPE_DEAUTH >> 4)
74 }
75};
76
Glen Lee73584a42016-01-25 16:35:10 +090077static const struct wiphy_wowlan_support wowlan_support = {
78 .flags = WIPHY_WOWLAN_ANY
79};
80
Arnd Bergmann15162fb2015-11-16 15:04:57 +010081#define WILC_WFI_DWELL_PASSIVE 100
82#define WILC_WFI_DWELL_ACTIVE 40
83
84#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
85#define DEFAULT_LINK_SPEED 72
86
87
Johnny Kimc5c77ba2015-05-11 14:30:56 +090088#define IS_MANAGMEMENT 0x100
89#define IS_MANAGMEMENT_CALLBACK 0x080
90#define IS_MGMT_STATUS_SUCCES 0x040
91#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
92
Arnd Bergmann0e1af732015-11-16 15:04:54 +010093extern int wilc_mac_open(struct net_device *ndev);
94extern int wilc_mac_close(struct net_device *ndev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090095
Leo Kim6b5180a2016-02-04 18:24:10 +090096static struct network_info last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
Leo Kim771fbae2015-11-19 15:56:10 +090097static u32 last_scanned_cnt;
Arnd Bergmann0e1af732015-11-16 15:04:54 +010098struct timer_list wilc_during_ip_timer;
Arnd Bergmann1608c402015-11-16 15:04:53 +010099static struct timer_list hAgingTimer;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +0900100static u8 op_ifcs;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900101
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100102u8 wilc_initialized = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900103
104#define CHAN2G(_channel, _freq, _flags) { \
Johannes Berg57fbcce2016-04-12 15:56:15 +0200105 .band = NL80211_BAND_2GHZ, \
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900106 .center_freq = (_freq), \
107 .hw_value = (_channel), \
108 .flags = (_flags), \
109 .max_antenna_gain = 0, \
110 .max_power = 30, \
111}
112
Leo Kim2736f472015-11-19 15:56:12 +0900113static struct ieee80211_channel ieee80211_2ghz_channels[] = {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900114 CHAN2G(1, 2412, 0),
115 CHAN2G(2, 2417, 0),
116 CHAN2G(3, 2422, 0),
117 CHAN2G(4, 2427, 0),
118 CHAN2G(5, 2432, 0),
119 CHAN2G(6, 2437, 0),
120 CHAN2G(7, 2442, 0),
121 CHAN2G(8, 2447, 0),
122 CHAN2G(9, 2452, 0),
123 CHAN2G(10, 2457, 0),
124 CHAN2G(11, 2462, 0),
125 CHAN2G(12, 2467, 0),
126 CHAN2G(13, 2472, 0),
127 CHAN2G(14, 2484, 0),
128};
129
130#define RATETAB_ENT(_rate, _hw_value, _flags) { \
131 .bitrate = (_rate), \
132 .hw_value = (_hw_value), \
133 .flags = (_flags), \
134}
135
Leo Kim8d48b5b2015-11-19 15:56:13 +0900136static struct ieee80211_rate ieee80211_bitrates[] = {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900137 RATETAB_ENT(10, 0, 0),
138 RATETAB_ENT(20, 1, 0),
139 RATETAB_ENT(55, 2, 0),
140 RATETAB_ENT(110, 3, 0),
141 RATETAB_ENT(60, 9, 0),
142 RATETAB_ENT(90, 6, 0),
143 RATETAB_ENT(120, 7, 0),
144 RATETAB_ENT(180, 8, 0),
145 RATETAB_ENT(240, 9, 0),
146 RATETAB_ENT(360, 10, 0),
147 RATETAB_ENT(480, 11, 0),
148 RATETAB_ENT(540, 12, 0),
149};
150
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900151struct p2p_mgmt_data {
152 int size;
153 u8 *buff;
154};
155
Leo Kim0bd82742015-11-19 15:56:14 +0900156static u8 wlan_channel = INVALID_CHANNEL;
Arnd Bergmann1608c402015-11-16 15:04:53 +0100157static u8 curr_channel;
Leo Kim881eb5d2015-11-19 15:56:15 +0900158static u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09};
Leo Kim583d9722015-11-19 15:56:16 +0900159static u8 p2p_local_random = 0x01;
Eva Rachel Retuyad38f5ba2016-02-15 13:34:17 +0800160static u8 p2p_recv_random;
Leo Kim86685942015-11-19 15:56:18 +0900161static u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
Leo Kima25d5182015-11-19 15:56:19 +0900162static bool wilc_ie;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900163
164static struct ieee80211_supported_band WILC_WFI_band_2ghz = {
Leo Kim2736f472015-11-19 15:56:12 +0900165 .channels = ieee80211_2ghz_channels,
166 .n_channels = ARRAY_SIZE(ieee80211_2ghz_channels),
Leo Kim8d48b5b2015-11-19 15:56:13 +0900167 .bitrates = ieee80211_bitrates,
168 .n_bitrates = ARRAY_SIZE(ieee80211_bitrates),
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900169};
170
171
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900172struct add_key_params {
173 u8 key_idx;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900174 bool pairwise;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900175 u8 *mac_addr;
176};
Arnd Bergmann1608c402015-11-16 15:04:53 +0100177static struct add_key_params g_add_gtk_key_params;
178static struct wilc_wfi_key g_key_gtk_params;
179static struct add_key_params g_add_ptk_key_params;
180static struct wilc_wfi_key g_key_ptk_params;
181static struct wilc_wfi_wep_key g_key_wep_params;
182static bool g_ptk_keys_saved;
183static bool g_gtk_keys_saved;
184static bool g_wep_keys_saved;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900185
186#define AGING_TIME (9 * 1000)
Leo Kim7e872df2015-11-19 15:56:20 +0900187#define during_ip_time 15000
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900188
Leo Kimd14991a2015-11-19 15:56:22 +0900189static void clear_shadow_scan(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900190{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900191 int i;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900192
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900193 if (op_ifcs == 0) {
Greg Kroah-Hartman4183e972015-08-14 20:11:16 -0700194 del_timer_sync(&hAgingTimer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900195
Leo Kim771fbae2015-11-19 15:56:10 +0900196 for (i = 0; i < last_scanned_cnt; i++) {
Leo Kim390b6db2016-02-04 18:24:23 +0900197 if (last_scanned_shadow[last_scanned_cnt].ies) {
198 kfree(last_scanned_shadow[i].ies);
199 last_scanned_shadow[last_scanned_cnt].ies = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900200 }
201
Leo Kimcb64de72016-02-04 18:24:24 +0900202 kfree(last_scanned_shadow[i].join_params);
203 last_scanned_shadow[i].join_params = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900204 }
Leo Kim771fbae2015-11-19 15:56:10 +0900205 last_scanned_cnt = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900206 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900207}
208
Leo Kim6b5180a2016-02-04 18:24:10 +0900209static u32 get_rssi_avg(struct network_info *network_info)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900210{
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900211 u8 i;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900212 int rssi_v = 0;
Leo Kimf2050a12016-02-04 18:24:25 +0900213 u8 num_rssi = (network_info->str_rssi.u8Full) ?
214 NUM_RSSI : (network_info->str_rssi.u8Index);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900215
216 for (i = 0; i < num_rssi; i++)
Leo Kimf2050a12016-02-04 18:24:25 +0900217 rssi_v += network_info->str_rssi.as8RSSI[i];
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900218
219 rssi_v /= num_rssi;
220 return rssi_v;
221}
222
Leo Kim48ee7ba2015-11-19 15:56:24 +0900223static void refresh_scan(void *user_void, u8 all, bool direct_scan)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900224{
Chaehyun Lim27268872015-09-15 14:06:13 +0900225 struct wilc_priv *priv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900226 struct wiphy *wiphy;
227 struct cfg80211_bss *bss = NULL;
228 int i;
229 int rssi = 0;
230
Alison Schofield4375cad2016-02-12 22:54:08 -0800231 priv = user_void;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900232 wiphy = priv->dev->ieee80211_ptr->wiphy;
233
Leo Kim771fbae2015-11-19 15:56:10 +0900234 for (i = 0; i < last_scanned_cnt; i++) {
Leo Kim6b5180a2016-02-04 18:24:10 +0900235 struct network_info *network_info;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900236
Leo Kimce3b1b52015-11-19 15:56:25 +0900237 network_info = &last_scanned_shadow[i];
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900238
Leo Kima35d6e2d2016-02-04 18:24:21 +0900239 if (!network_info->found || all) {
Leo Kimc6f5e3a2015-11-19 15:56:26 +0900240 s32 freq;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900241 struct ieee80211_channel *channel;
242
Leo Kimce3b1b52015-11-19 15:56:25 +0900243 if (network_info) {
Johannes Berg57fbcce2016-04-12 15:56:15 +0200244 freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ);
Leo Kimc6f5e3a2015-11-19 15:56:26 +0900245 channel = ieee80211_get_channel(wiphy, freq);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900246
Leo Kimce3b1b52015-11-19 15:56:25 +0900247 rssi = get_rssi_avg(network_info);
Leo Kim2a3ff582016-02-04 18:24:13 +0900248 if (memcmp("DIRECT-", network_info->ssid, 7) ||
Leo Kim48ee7ba2015-11-19 15:56:24 +0900249 direct_scan) {
Leo Kimfa5e2d12016-02-04 18:24:12 +0900250 bss = cfg80211_inform_bss(wiphy,
251 channel,
252 CFG80211_BSS_FTYPE_UNKNOWN,
Leo Kim38d3bb72016-02-04 18:24:15 +0900253 network_info->bssid,
Leo Kim17d2f2b2016-02-04 18:24:26 +0900254 network_info->tsf_hi,
Leo Kimfa5e2d12016-02-04 18:24:12 +0900255 network_info->cap_info,
Leo Kim4b313e92016-02-04 18:24:16 +0900256 network_info->beacon_period,
Leo Kim390b6db2016-02-04 18:24:23 +0900257 (const u8 *)network_info->ies,
258 (size_t)network_info->ies_len,
Leo Kimfa5e2d12016-02-04 18:24:12 +0900259 (s32)rssi * 100,
260 GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900261 cfg80211_put_bss(wiphy, bss);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900262 }
263 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900264 }
265 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900266}
267
Leo Kim12b01382015-11-19 15:56:27 +0900268static void reset_shadow_found(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900269{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900270 int i;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900271
Leo Kim771fbae2015-11-19 15:56:10 +0900272 for (i = 0; i < last_scanned_cnt; i++)
Leo Kima35d6e2d2016-02-04 18:24:21 +0900273 last_scanned_shadow[i].found = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900274}
275
Leo Kim5e51d8b2015-11-19 15:56:28 +0900276static void update_scan_time(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900277{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900278 int i;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900279
Leo Kim771fbae2015-11-19 15:56:10 +0900280 for (i = 0; i < last_scanned_cnt; i++)
Leo Kim264d70f2016-02-04 18:24:19 +0900281 last_scanned_shadow[i].time_scan = jiffies;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900282}
283
Greg Kroah-Hartman93dee8e2015-08-14 20:28:32 -0700284static void remove_network_from_shadow(unsigned long arg)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900285{
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900286 unsigned long now = jiffies;
287 int i, j;
288
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900289
Leo Kim771fbae2015-11-19 15:56:10 +0900290 for (i = 0; i < last_scanned_cnt; i++) {
Leo Kim264d70f2016-02-04 18:24:19 +0900291 if (time_after(now, last_scanned_shadow[i].time_scan +
292 (unsigned long)(SCAN_RESULT_EXPIRE))) {
Leo Kim390b6db2016-02-04 18:24:23 +0900293 kfree(last_scanned_shadow[i].ies);
294 last_scanned_shadow[i].ies = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900295
Leo Kimcb64de72016-02-04 18:24:24 +0900296 kfree(last_scanned_shadow[i].join_params);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900297
Leo Kim771fbae2015-11-19 15:56:10 +0900298 for (j = i; (j < last_scanned_cnt - 1); j++)
Leo Kimf1ab1172015-11-19 15:56:11 +0900299 last_scanned_shadow[j] = last_scanned_shadow[j + 1];
Leo Kim771fbae2015-11-19 15:56:10 +0900300
301 last_scanned_cnt--;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900302 }
303 }
304
Leo Kim771fbae2015-11-19 15:56:10 +0900305 if (last_scanned_cnt != 0) {
Greg Kroah-Hartman9eb06642015-08-17 11:10:55 -0700306 hAgingTimer.data = arg;
307 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
Greg Kroah-Hartman9eb06642015-08-17 11:10:55 -0700308 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900309}
310
Greg Kroah-Hartman93dee8e2015-08-14 20:28:32 -0700311static void clear_duringIP(unsigned long arg)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900312{
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100313 wilc_optaining_ip = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900314}
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900315
Leo Kim6b5180a2016-02-04 18:24:10 +0900316static int is_network_in_shadow(struct network_info *pstrNetworkInfo,
Leo Kim157814f2015-11-19 15:56:29 +0900317 void *user_void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900318{
Chaehyun Lima74cc6b2015-10-02 16:41:17 +0900319 int state = -1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900320 int i;
321
Leo Kim771fbae2015-11-19 15:56:10 +0900322 if (last_scanned_cnt == 0) {
Leo Kim157814f2015-11-19 15:56:29 +0900323 hAgingTimer.data = (unsigned long)user_void;
Greg Kroah-Hartman9eb06642015-08-17 11:10:55 -0700324 mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900325 state = -1;
326 } else {
Leo Kim771fbae2015-11-19 15:56:10 +0900327 for (i = 0; i < last_scanned_cnt; i++) {
Leo Kim38d3bb72016-02-04 18:24:15 +0900328 if (memcmp(last_scanned_shadow[i].bssid,
329 pstrNetworkInfo->bssid, 6) == 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900330 state = i;
331 break;
332 }
333 }
334 }
335 return state;
336}
337
Leo Kim6b5180a2016-02-04 18:24:10 +0900338static void add_network_to_shadow(struct network_info *pstrNetworkInfo,
Leo Kim5c4cf0d2015-11-19 15:56:30 +0900339 void *user_void, void *pJoinParams)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900340{
Leo Kim5c4cf0d2015-11-19 15:56:30 +0900341 int ap_found = is_network_in_shadow(pstrNetworkInfo, user_void);
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900342 u32 ap_index = 0;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900343 u8 rssi_index = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900344
Chris Park64d35462016-02-22 13:11:57 +0900345 if (last_scanned_cnt >= MAX_NUM_SCANNED_NETWORKS_SHADOW)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900346 return;
Chris Park64d35462016-02-22 13:11:57 +0900347
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900348 if (ap_found == -1) {
Leo Kim771fbae2015-11-19 15:56:10 +0900349 ap_index = last_scanned_cnt;
350 last_scanned_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900351 } else {
352 ap_index = ap_found;
353 }
Leo Kimf2050a12016-02-04 18:24:25 +0900354 rssi_index = last_scanned_shadow[ap_index].str_rssi.u8Index;
355 last_scanned_shadow[ap_index].str_rssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900356 if (rssi_index == NUM_RSSI) {
357 rssi_index = 0;
Leo Kimf2050a12016-02-04 18:24:25 +0900358 last_scanned_shadow[ap_index].str_rssi.u8Full = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900359 }
Leo Kimf2050a12016-02-04 18:24:25 +0900360 last_scanned_shadow[ap_index].str_rssi.u8Index = rssi_index;
Leo Kim5c23a292016-02-04 18:24:11 +0900361 last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi;
Leo Kimfa5e2d12016-02-04 18:24:12 +0900362 last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info;
Leo Kima36e89e2016-02-04 18:24:14 +0900363 last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len;
Leo Kim2a3ff582016-02-04 18:24:13 +0900364 memcpy(last_scanned_shadow[ap_index].ssid,
Leo Kima36e89e2016-02-04 18:24:14 +0900365 pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len);
Leo Kim38d3bb72016-02-04 18:24:15 +0900366 memcpy(last_scanned_shadow[ap_index].bssid,
367 pstrNetworkInfo->bssid, ETH_ALEN);
Leo Kim4b313e92016-02-04 18:24:16 +0900368 last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period;
Leo Kimdf340fd2016-02-04 18:24:17 +0900369 last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period;
Leo Kim405a8c72016-02-04 18:24:18 +0900370 last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch;
Leo Kim390b6db2016-02-04 18:24:23 +0900371 last_scanned_shadow[ap_index].ies_len = pstrNetworkInfo->ies_len;
Leo Kim17d2f2b2016-02-04 18:24:26 +0900372 last_scanned_shadow[ap_index].tsf_hi = pstrNetworkInfo->tsf_hi;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900373 if (ap_found != -1)
Leo Kim390b6db2016-02-04 18:24:23 +0900374 kfree(last_scanned_shadow[ap_index].ies);
375 last_scanned_shadow[ap_index].ies = kmalloc(pstrNetworkInfo->ies_len,
376 GFP_KERNEL);
377 memcpy(last_scanned_shadow[ap_index].ies,
378 pstrNetworkInfo->ies, pstrNetworkInfo->ies_len);
Leo Kim264d70f2016-02-04 18:24:19 +0900379 last_scanned_shadow[ap_index].time_scan = jiffies;
380 last_scanned_shadow[ap_index].time_scan_cached = jiffies;
Leo Kima35d6e2d2016-02-04 18:24:21 +0900381 last_scanned_shadow[ap_index].found = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900382 if (ap_found != -1)
Leo Kimcb64de72016-02-04 18:24:24 +0900383 kfree(last_scanned_shadow[ap_index].join_params);
384 last_scanned_shadow[ap_index].join_params = pJoinParams;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900385}
386
Leo Kim1a4c8ce2015-11-19 15:56:31 +0900387static void CfgScanResult(enum scan_event scan_event,
Leo Kim6b5180a2016-02-04 18:24:10 +0900388 struct network_info *network_info,
Leo Kim30cd10c2015-11-19 15:56:33 +0900389 void *user_void,
Leo Kimbdd34602015-11-19 15:56:34 +0900390 void *join_params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900391{
Chaehyun Lim27268872015-09-15 14:06:13 +0900392 struct wilc_priv *priv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900393 struct wiphy *wiphy;
Chaehyun Limfb4ec9c2015-06-11 14:35:59 +0900394 s32 s32Freq;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900395 struct ieee80211_channel *channel;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900396 struct cfg80211_bss *bss = NULL;
397
Alison Schofield4375cad2016-02-12 22:54:08 -0800398 priv = user_void;
Luis de Bethencourt7e4e87d2015-10-16 16:32:26 +0100399 if (priv->bCfgScanning) {
Leo Kim1a4c8ce2015-11-19 15:56:31 +0900400 if (scan_event == SCAN_EVENT_NETWORK_FOUND) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900401 wiphy = priv->dev->ieee80211_ptr->wiphy;
Leo Kim7ae43362015-09-16 18:35:59 +0900402
403 if (!wiphy)
404 return;
405
Leo Kim0551a722015-11-19 15:56:32 +0900406 if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
Leo Kim5c23a292016-02-04 18:24:11 +0900407 (((s32)network_info->rssi * 100) < 0 ||
408 ((s32)network_info->rssi * 100) > 100))
Leo Kim24db7132015-09-16 18:36:01 +0900409 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900410
Leo Kim0551a722015-11-19 15:56:32 +0900411 if (network_info) {
Johannes Berg57fbcce2016-04-12 15:56:15 +0200412 s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900413 channel = ieee80211_get_channel(wiphy, s32Freq);
414
Leo Kim7ae43362015-09-16 18:35:59 +0900415 if (!channel)
416 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900417
Leo Kimd4020762016-02-04 18:24:20 +0900418 if (network_info->new_network) {
Leo Kima89f7c52015-11-25 11:59:41 +0900419 if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900420 priv->u32RcvdChCount++;
421
Leo Kimbdd34602015-11-19 15:56:34 +0900422 add_network_to_shadow(network_info, priv, join_params);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900423
Leo Kim2a3ff582016-02-04 18:24:13 +0900424 if (!(memcmp("DIRECT-", network_info->ssid, 7))) {
Leo Kimfa5e2d12016-02-04 18:24:12 +0900425 bss = cfg80211_inform_bss(wiphy,
426 channel,
427 CFG80211_BSS_FTYPE_UNKNOWN,
Leo Kim38d3bb72016-02-04 18:24:15 +0900428 network_info->bssid,
Leo Kim17d2f2b2016-02-04 18:24:26 +0900429 network_info->tsf_hi,
Leo Kimfa5e2d12016-02-04 18:24:12 +0900430 network_info->cap_info,
Leo Kim4b313e92016-02-04 18:24:16 +0900431 network_info->beacon_period,
Leo Kim390b6db2016-02-04 18:24:23 +0900432 (const u8 *)network_info->ies,
433 (size_t)network_info->ies_len,
Leo Kimfa5e2d12016-02-04 18:24:12 +0900434 (s32)network_info->rssi * 100,
435 GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900436 cfg80211_put_bss(wiphy, bss);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900437 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900438 }
439 } else {
Chaehyun Lim4e4467f2015-06-11 14:35:55 +0900440 u32 i;
Leo Kima89f7c52015-11-25 11:59:41 +0900441
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900442 for (i = 0; i < priv->u32RcvdChCount; i++) {
Leo Kim38d3bb72016-02-04 18:24:15 +0900443 if (memcmp(last_scanned_shadow[i].bssid, network_info->bssid, 6) == 0) {
Leo Kim5c23a292016-02-04 18:24:11 +0900444 last_scanned_shadow[i].rssi = network_info->rssi;
Leo Kim264d70f2016-02-04 18:24:19 +0900445 last_scanned_shadow[i].time_scan = jiffies;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900446 break;
447 }
448 }
449 }
450 }
Leo Kim1a4c8ce2015-11-19 15:56:31 +0900451 } else if (scan_event == SCAN_EVENT_DONE) {
Dean Lee72ed4dc2015-06-12 14:11:44 +0900452 refresh_scan(priv, 1, false);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900453
Chaehyun Lim08662092016-03-28 13:56:00 +0900454 mutex_lock(&priv->scan_req_lock);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900455
Leo Kim369a1d32015-12-21 14:18:23 +0900456 if (priv->pstrScanReq) {
Avraham Stern1d762502016-07-05 17:10:13 +0300457 struct cfg80211_scan_info info = {
458 .aborted = false,
459 };
460
461 cfg80211_scan_done(priv->pstrScanReq, &info);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900462 priv->u32RcvdChCount = 0;
Dean Lee72ed4dc2015-06-12 14:11:44 +0900463 priv->bCfgScanning = false;
Greg Kroah-Hartmanb1413b62015-06-02 14:11:12 +0900464 priv->pstrScanReq = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900465 }
Chaehyun Lim08662092016-03-28 13:56:00 +0900466 mutex_unlock(&priv->scan_req_lock);
Leo Kim1a4c8ce2015-11-19 15:56:31 +0900467 } else if (scan_event == SCAN_EVENT_ABORTED) {
Chaehyun Lim08662092016-03-28 13:56:00 +0900468 mutex_lock(&priv->scan_req_lock);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900469
Leo Kim369a1d32015-12-21 14:18:23 +0900470 if (priv->pstrScanReq) {
Avraham Stern1d762502016-07-05 17:10:13 +0300471 struct cfg80211_scan_info info = {
472 .aborted = false,
473 };
474
Leo Kim5e51d8b2015-11-19 15:56:28 +0900475 update_scan_time();
Dean Lee72ed4dc2015-06-12 14:11:44 +0900476 refresh_scan(priv, 1, false);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900477
Avraham Stern1d762502016-07-05 17:10:13 +0300478 cfg80211_scan_done(priv->pstrScanReq, &info);
Dean Lee72ed4dc2015-06-12 14:11:44 +0900479 priv->bCfgScanning = false;
Greg Kroah-Hartmanb1413b62015-06-02 14:11:12 +0900480 priv->pstrScanReq = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900481 }
Chaehyun Lim08662092016-03-28 13:56:00 +0900482 mutex_unlock(&priv->scan_req_lock);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900483 }
484 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900485}
486
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100487int wilc_connecting;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900488
Leo Kimed3f0372015-10-12 16:56:01 +0900489static void CfgConnectResult(enum conn_event enuConnDisconnEvent,
Chaehyun Lim3b0437e2016-02-25 09:15:42 +0900490 struct connect_info *pstrConnectInfo,
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +0900491 u8 u8MacStatus,
Chaehyun Limbb76df52016-02-25 09:15:49 +0900492 struct disconnect_info *pstrDisconnectNotifInfo,
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900493 void *pUserVoid)
494{
Chaehyun Lim27268872015-09-15 14:06:13 +0900495 struct wilc_priv *priv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900496 struct net_device *dev;
Leo Kim441dc602015-10-12 16:55:35 +0900497 struct host_if_drv *pstrWFIDrv;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +0900498 u8 NullBssid[ETH_ALEN] = {0};
Glen Leec1ec2c12015-10-20 17:13:58 +0900499 struct wilc *wl;
Glen Leea4cac482015-12-21 14:18:36 +0900500 struct wilc_vif *vif;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900501
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100502 wilc_connecting = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900503
Alison Schofield4375cad2016-02-12 22:54:08 -0800504 priv = pUserVoid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900505 dev = priv->dev;
Glen Leea4cac482015-12-21 14:18:36 +0900506 vif = netdev_priv(dev);
507 wl = vif->wilc;
Leo Kim48b28df2016-02-04 18:15:32 +0900508 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900509
510 if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) {
Amitoj Kaur Chawlababa7c72015-10-15 13:48:29 +0530511 u16 u16ConnectStatus;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900512
Chaehyun Lim134b4cf2016-02-25 09:15:48 +0900513 u16ConnectStatus = pstrConnectInfo->status;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900514
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900515 if ((u8MacStatus == MAC_DISCONNECTED) &&
Chaehyun Lim134b4cf2016-02-25 09:15:48 +0900516 (pstrConnectInfo->status == SUCCESSFUL_STATUSCODE)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900517 u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
Glen Leeba615f12016-01-25 16:35:15 +0900518 wilc_wlan_set_bssid(priv->dev, NullBssid,
519 STATION_MODE);
Leo Kime554a302015-11-19 15:56:21 +0900520 eth_zero_addr(wilc_connected_ssid);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900521
Leo Kimab16ec02015-10-29 12:05:40 +0900522 if (!pstrWFIDrv->p2p_connect)
Leo Kim0bd82742015-11-19 15:56:14 +0900523 wlan_channel = INVALID_CHANNEL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900524
Leo Kim06fb9332016-02-04 18:15:55 +0900525 netdev_err(dev, "Unspecified failure\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900526 }
527
528 if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
Dean Lee72ed4dc2015-06-12 14:11:44 +0900529 bool bNeedScanRefresh = false;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +0900530 u32 i;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900531
Chaehyun Limd4a24e02016-02-25 09:15:43 +0900532 memcpy(priv->au8AssociatedBss, pstrConnectInfo->bssid, ETH_ALEN);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900533
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900534
Leo Kim771fbae2015-11-19 15:56:10 +0900535 for (i = 0; i < last_scanned_cnt; i++) {
Leo Kim38d3bb72016-02-04 18:24:15 +0900536 if (memcmp(last_scanned_shadow[i].bssid,
Chaehyun Limd4a24e02016-02-25 09:15:43 +0900537 pstrConnectInfo->bssid,
Leo Kim38d3bb72016-02-04 18:24:15 +0900538 ETH_ALEN) == 0) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900539 unsigned long now = jiffies;
540
541 if (time_after(now,
Leo Kim264d70f2016-02-04 18:24:19 +0900542 last_scanned_shadow[i].time_scan_cached +
543 (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ))))
Dean Lee72ed4dc2015-06-12 14:11:44 +0900544 bNeedScanRefresh = true;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900545
546 break;
547 }
548 }
549
Leo Kima89f7c52015-11-25 11:59:41 +0900550 if (bNeedScanRefresh)
Dean Lee72ed4dc2015-06-12 14:11:44 +0900551 refresh_scan(priv, 1, true);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900552 }
553
Chaehyun Limd4a24e02016-02-25 09:15:43 +0900554 cfg80211_connect_result(dev, pstrConnectInfo->bssid,
Chaehyun Lim4607f9c2016-02-25 09:15:45 +0900555 pstrConnectInfo->req_ies, pstrConnectInfo->req_ies_len,
Chaehyun Lim3e7477c2016-02-25 09:15:47 +0900556 pstrConnectInfo->resp_ies, pstrConnectInfo->resp_ies_len,
Leo Kima89f7c52015-11-25 11:59:41 +0900557 u16ConnectStatus, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900558 } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) {
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100559 wilc_optaining_ip = false;
Leo Kim583d9722015-11-19 15:56:16 +0900560 p2p_local_random = 0x01;
Leo Kimb84a3ac2015-11-19 15:56:17 +0900561 p2p_recv_random = 0x00;
Leo Kima25d5182015-11-19 15:56:19 +0900562 wilc_ie = false;
Shraddha Barkebcf02652015-10-05 17:00:32 +0530563 eth_zero_addr(priv->au8AssociatedBss);
Glen Leeba615f12016-01-25 16:35:15 +0900564 wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
Leo Kime554a302015-11-19 15:56:21 +0900565 eth_zero_addr(wilc_connected_ssid);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900566
Leo Kimab16ec02015-10-29 12:05:40 +0900567 if (!pstrWFIDrv->p2p_connect)
Leo Kim0bd82742015-11-19 15:56:14 +0900568 wlan_channel = INVALID_CHANNEL;
Roger H. Newelld5e27e82016-03-19 12:49:21 -0230569 if ((pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev))
Chaehyun Lim90f209d2016-02-25 09:15:50 +0900570 pstrDisconnectNotifInfo->reason = 3;
Roger H. Newelld5e27e82016-03-19 12:49:21 -0230571 else if ((!pstrWFIDrv->IFC_UP) && (dev == wl->vif[1]->ndev))
Chaehyun Lim90f209d2016-02-25 09:15:50 +0900572 pstrDisconnectNotifInfo->reason = 1;
Roger H. Newelld5e27e82016-03-19 12:49:21 -0230573
Chaehyun Lim90f209d2016-02-25 09:15:50 +0900574 cfg80211_disconnected(dev, pstrDisconnectNotifInfo->reason, pstrDisconnectNotifInfo->ie,
Sudip Mukherjeee26bb712015-06-30 13:51:51 +0530575 pstrDisconnectNotifInfo->ie_len, false,
576 GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900577 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900578}
579
Chaehyun Lim80785a92015-09-14 12:24:01 +0900580static int set_channel(struct wiphy *wiphy,
581 struct cfg80211_chan_def *chandef)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900582{
Chaehyun Lim4e4467f2015-06-11 14:35:55 +0900583 u32 channelnum = 0;
Chaehyun Lim27268872015-09-15 14:06:13 +0900584 struct wilc_priv *priv;
Chaehyun Limdd739ea2015-10-02 16:41:20 +0900585 int result = 0;
Glen Leecf601062015-12-21 14:18:39 +0900586 struct wilc_vif *vif;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900587
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900588 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +0900589 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900590
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900591 channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900592
Chaehyun Lim866a2c22015-10-02 16:41:21 +0900593 curr_channel = channelnum;
Glen Leefbf53792015-12-21 14:18:40 +0900594 result = wilc_set_mac_chnl_num(vif, channelnum);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900595
Chaehyun Limdd739ea2015-10-02 16:41:20 +0900596 if (result != 0)
Leo Kim06fb9332016-02-04 18:15:55 +0900597 netdev_err(priv->dev, "Error in setting channel\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900598
Chaehyun Limdd739ea2015-10-02 16:41:20 +0900599 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900600}
601
Chaehyun Lim0e30d062015-09-14 12:24:02 +0900602static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900603{
Chaehyun Lim27268872015-09-15 14:06:13 +0900604 struct wilc_priv *priv;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +0900605 u32 i;
Leo Kime6e12662015-09-16 18:36:03 +0900606 s32 s32Error = 0;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +0900607 u8 au8ScanChanList[MAX_NUM_SCANNED_NETWORKS];
Leo Kim607db442015-10-05 15:25:37 +0900608 struct hidden_network strHiddenNetwork;
Glen Leecf601062015-12-21 14:18:39 +0900609 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900610
611 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +0900612 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900613
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900614 priv->pstrScanReq = request;
615
616 priv->u32RcvdChCount = 0;
617
Leo Kim12b01382015-11-19 15:56:27 +0900618 reset_shadow_found();
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900619
Dean Lee72ed4dc2015-06-12 14:11:44 +0900620 priv->bCfgScanning = true;
Leo Kima89f7c52015-11-25 11:59:41 +0900621 if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) {
Chris Park64d35462016-02-22 13:11:57 +0900622 for (i = 0; i < request->n_channels; i++)
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +0900623 au8ScanChanList[i] = (u8)ieee80211_frequency_to_channel(request->channels[i]->center_freq);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900624
625 if (request->n_ssids >= 1) {
Janani Ravichandran8459af62016-02-16 17:27:03 -0500626 strHiddenNetwork.net_info =
627 kmalloc_array(request->n_ssids,
628 sizeof(struct hidden_network),
629 GFP_KERNEL);
Leo Kim396fa302016-02-22 13:11:50 +0900630 if (!strHiddenNetwork.net_info)
631 return -ENOMEM;
Chaehyun Lim40e05e82016-01-05 13:26:33 +0900632 strHiddenNetwork.n_ssids = request->n_ssids;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900633
634
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900635 for (i = 0; i < request->n_ssids; i++) {
Luis de Bethencourt4562d222016-06-23 18:57:09 +0100636 if (request->ssids[i].ssid_len != 0) {
Chaehyun Lim245a1862016-01-05 13:26:32 +0900637 strHiddenNetwork.net_info[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL);
638 memcpy(strHiddenNetwork.net_info[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
639 strHiddenNetwork.net_info[i].ssid_len = request->ssids[i].ssid_len;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900640 } else {
Chaehyun Lim40e05e82016-01-05 13:26:33 +0900641 strHiddenNetwork.n_ssids -= 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900642 }
643 }
Glen Leefbf53792015-12-21 14:18:40 +0900644 s32Error = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
645 au8ScanChanList,
646 request->n_channels,
647 (const u8 *)request->ie,
648 request->ie_len, CfgScanResult,
649 (void *)priv, &strHiddenNetwork);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900650 } else {
Glen Leefbf53792015-12-21 14:18:40 +0900651 s32Error = wilc_scan(vif, USER_SCAN, ACTIVE_SCAN,
652 au8ScanChanList,
653 request->n_channels,
654 (const u8 *)request->ie,
655 request->ie_len, CfgScanResult,
656 (void *)priv, NULL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900657 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900658 } else {
Leo Kim06fb9332016-02-04 18:15:55 +0900659 netdev_err(priv->dev, "Requested scanned channels over\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900660 }
661
Chris Park64d35462016-02-22 13:11:57 +0900662 if (s32Error != 0)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900663 s32Error = -EBUSY;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900664
665 return s32Error;
666}
667
Chaehyun Lim4ffbcdb2015-09-14 12:24:03 +0900668static int connect(struct wiphy *wiphy, struct net_device *dev,
669 struct cfg80211_connect_params *sme)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900670{
Leo Kime6e12662015-09-16 18:36:03 +0900671 s32 s32Error = 0;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +0900672 u32 i;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +0900673 u8 u8security = NO_ENCRYPT;
Leo Kim841dfc42015-10-05 15:25:39 +0900674 enum AUTHTYPE tenuAuth_type = ANY;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900675
Chaehyun Lim27268872015-09-15 14:06:13 +0900676 struct wilc_priv *priv;
Leo Kim441dc602015-10-12 16:55:35 +0900677 struct host_if_drv *pstrWFIDrv;
Leo Kim6b5180a2016-02-04 18:24:10 +0900678 struct network_info *pstrNetworkInfo = NULL;
Glen Leecf601062015-12-21 14:18:39 +0900679 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900680
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100681 wilc_connecting = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900682 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +0900683 vif = netdev_priv(priv->dev);
Leo Kim48b28df2016-02-04 18:15:32 +0900684 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900685
Chris Park64d35462016-02-22 13:11:57 +0900686 if (!(strncmp(sme->ssid, "DIRECT-", 7)))
Leo Kimab16ec02015-10-29 12:05:40 +0900687 pstrWFIDrv->p2p_connect = 1;
Chris Park64d35462016-02-22 13:11:57 +0900688 else
Leo Kimab16ec02015-10-29 12:05:40 +0900689 pstrWFIDrv->p2p_connect = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900690
Leo Kim771fbae2015-11-19 15:56:10 +0900691 for (i = 0; i < last_scanned_cnt; i++) {
Leo Kima36e89e2016-02-04 18:24:14 +0900692 if ((sme->ssid_len == last_scanned_shadow[i].ssid_len) &&
Leo Kim2a3ff582016-02-04 18:24:13 +0900693 memcmp(last_scanned_shadow[i].ssid,
Leo Kimf1ab1172015-11-19 15:56:11 +0900694 sme->ssid,
695 sme->ssid_len) == 0) {
Chris Park64d35462016-02-22 13:11:57 +0900696 if (!sme->bssid)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900697 break;
Chris Park64d35462016-02-22 13:11:57 +0900698 else
Leo Kim38d3bb72016-02-04 18:24:15 +0900699 if (memcmp(last_scanned_shadow[i].bssid,
Leo Kimf1ab1172015-11-19 15:56:11 +0900700 sme->bssid,
Chris Park64d35462016-02-22 13:11:57 +0900701 ETH_ALEN) == 0)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900702 break;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900703 }
704 }
705
Leo Kim771fbae2015-11-19 15:56:10 +0900706 if (i < last_scanned_cnt) {
Leo Kimf1ab1172015-11-19 15:56:11 +0900707 pstrNetworkInfo = &last_scanned_shadow[i];
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900708 } else {
709 s32Error = -ENOENT;
Glen Lee430e6402016-02-04 18:15:21 +0900710 wilc_connecting = 0;
711 return s32Error;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900712 }
713
Chaehyun Lim2cc46832015-08-07 09:02:01 +0900714 memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
715 memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900716
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900717 if (sme->crypto.cipher_group != NO_ENCRYPT) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900718 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900719 u8security = ENCRYPT_ENABLED | WEP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900720
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900721 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
Chaehyun Limd00d2ba2015-08-10 11:33:19 +0900722 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900723
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900724 g_key_wep_params.key_len = sme->key_len;
Glen Leef3052582015-09-10 12:03:04 +0900725 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900726 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
727 g_key_wep_params.key_idx = sme->key_idx;
Dean Lee72ed4dc2015-06-12 14:11:44 +0900728 g_wep_keys_saved = true;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900729
Glen Leefbf53792015-12-21 14:18:40 +0900730 wilc_set_wep_default_keyid(vif, sme->key_idx);
731 wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len,
732 sme->key_idx);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900733 } else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900734 u8security = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900735
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900736 priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
Chaehyun Limd00d2ba2015-08-10 11:33:19 +0900737 memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900738
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900739 g_key_wep_params.key_len = sme->key_len;
Glen Leef3052582015-09-10 12:03:04 +0900740 g_key_wep_params.key = kmalloc(sme->key_len, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900741 memcpy(g_key_wep_params.key, sme->key, sme->key_len);
742 g_key_wep_params.key_idx = sme->key_idx;
Dean Lee72ed4dc2015-06-12 14:11:44 +0900743 g_wep_keys_saved = true;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900744
Glen Leefbf53792015-12-21 14:18:40 +0900745 wilc_set_wep_default_keyid(vif, sme->key_idx);
746 wilc_add_wep_key_bss_sta(vif, sme->key, sme->key_len,
747 sme->key_idx);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900748 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
Roger H. Newelld5e27e82016-03-19 12:49:21 -0230749 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900750 u8security = ENCRYPT_ENABLED | WPA2 | TKIP;
Roger H. Newelld5e27e82016-03-19 12:49:21 -0230751 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900752 u8security = ENCRYPT_ENABLED | WPA2 | AES;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900753 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {
Roger H. Newelld5e27e82016-03-19 12:49:21 -0230754 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_TKIP)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900755 u8security = ENCRYPT_ENABLED | WPA | TKIP;
Roger H. Newelld5e27e82016-03-19 12:49:21 -0230756 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900757 u8security = ENCRYPT_ENABLED | WPA | AES;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900758 } else {
759 s32Error = -ENOTSUPP;
Leo Kim06fb9332016-02-04 18:15:55 +0900760 netdev_err(dev, "Not supported cipher\n");
Glen Lee430e6402016-02-04 18:15:21 +0900761 wilc_connecting = 0;
762 return s32Error;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900763 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900764 }
765
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900766 if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
767 || (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
768 for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) {
Roger H. Newelld5e27e82016-03-19 12:49:21 -0230769 if (sme->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900770 u8security = u8security | TKIP;
Roger H. Newelld5e27e82016-03-19 12:49:21 -0230771 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900772 u8security = u8security | AES;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900773 }
774 }
775
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900776 switch (sme->auth_type) {
777 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900778 tenuAuth_type = OPEN_SYSTEM;
779 break;
780
781 case NL80211_AUTHTYPE_SHARED_KEY:
782 tenuAuth_type = SHARED_KEY;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900783 break;
784
785 default:
Chris Park40bbaac2016-02-22 13:11:58 +0900786 break;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900787 }
788
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900789 if (sme->crypto.n_akm_suites) {
790 switch (sme->crypto.akm_suites[0]) {
791 case WLAN_AKM_SUITE_8021X:
792 tenuAuth_type = IEEE8021;
793 break;
794
795 default:
796 break;
797 }
798 }
799
Leo Kim405a8c72016-02-04 18:24:18 +0900800 curr_channel = pstrNetworkInfo->ch;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900801
Leo Kimab16ec02015-10-29 12:05:40 +0900802 if (!pstrWFIDrv->p2p_connect)
Leo Kim405a8c72016-02-04 18:24:18 +0900803 wlan_channel = pstrNetworkInfo->ch;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900804
Leo Kim38d3bb72016-02-04 18:24:15 +0900805 wilc_wlan_set_bssid(dev, pstrNetworkInfo->bssid, STATION_MODE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900806
Leo Kim38d3bb72016-02-04 18:24:15 +0900807 s32Error = wilc_set_join_req(vif, pstrNetworkInfo->bssid, sme->ssid,
Glen Leefbf53792015-12-21 14:18:40 +0900808 sme->ssid_len, sme->ie, sme->ie_len,
809 CfgConnectResult, (void *)priv,
810 u8security, tenuAuth_type,
Leo Kim405a8c72016-02-04 18:24:18 +0900811 pstrNetworkInfo->ch,
Leo Kimcb64de72016-02-04 18:24:24 +0900812 pstrNetworkInfo->join_params);
Leo Kime6e12662015-09-16 18:36:03 +0900813 if (s32Error != 0) {
Leo Kim06fb9332016-02-04 18:15:55 +0900814 netdev_err(dev, "wilc_set_join_req(): Error\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900815 s32Error = -ENOENT;
Glen Lee430e6402016-02-04 18:15:21 +0900816 wilc_connecting = 0;
817 return s32Error;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900818 }
819
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900820 return s32Error;
821}
822
Chaehyun Limb027cde2015-09-14 12:24:04 +0900823static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900824{
Leo Kime6e12662015-09-16 18:36:03 +0900825 s32 s32Error = 0;
Chaehyun Lim27268872015-09-15 14:06:13 +0900826 struct wilc_priv *priv;
Leo Kim441dc602015-10-12 16:55:35 +0900827 struct host_if_drv *pstrWFIDrv;
Glen Leecf601062015-12-21 14:18:39 +0900828 struct wilc_vif *vif;
Leo Kim80061092016-04-01 17:44:18 +0900829 struct wilc *wilc;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900830 u8 NullBssid[ETH_ALEN] = {0};
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900831
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100832 wilc_connecting = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900833 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +0900834 vif = netdev_priv(priv->dev);
Leo Kim80061092016-04-01 17:44:18 +0900835 wilc = vif->wilc;
836
837 if (!wilc)
838 return -EIO;
839
840 if (wilc->close) {
841 /* already disconnected done */
842 cfg80211_disconnected(dev, 0, NULL, 0, true, GFP_KERNEL);
843 return 0;
844 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900845
Leo Kim48b28df2016-02-04 18:15:32 +0900846 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
Leo Kimab16ec02015-10-29 12:05:40 +0900847 if (!pstrWFIDrv->p2p_connect)
Leo Kim0bd82742015-11-19 15:56:14 +0900848 wlan_channel = INVALID_CHANNEL;
Glen Leeba615f12016-01-25 16:35:15 +0900849 wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900850
Leo Kim583d9722015-11-19 15:56:16 +0900851 p2p_local_random = 0x01;
Leo Kimb84a3ac2015-11-19 15:56:17 +0900852 p2p_recv_random = 0x00;
Leo Kima25d5182015-11-19 15:56:19 +0900853 wilc_ie = false;
Leo Kim1229b1a2015-10-29 12:05:39 +0900854 pstrWFIDrv->p2p_timeout = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900855
Glen Leefbf53792015-12-21 14:18:40 +0900856 s32Error = wilc_disconnect(vif, reason_code);
Leo Kime6e12662015-09-16 18:36:03 +0900857 if (s32Error != 0) {
Leo Kim06fb9332016-02-04 18:15:55 +0900858 netdev_err(priv->dev, "Error in disconnecting\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900859 s32Error = -EINVAL;
860 }
861
862 return s32Error;
863}
864
Chaehyun Lim953d4172015-09-14 12:24:05 +0900865static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
866 bool pairwise,
867 const u8 *mac_addr, struct key_params *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900868
869{
Leo Kime6e12662015-09-16 18:36:03 +0900870 s32 s32Error = 0, KeyLen = params->key_len;
Chaehyun Lim27268872015-09-15 14:06:13 +0900871 struct wilc_priv *priv;
Arnd Bergmann057d1e92015-06-01 21:06:44 +0200872 const u8 *pu8RxMic = NULL;
873 const u8 *pu8TxMic = NULL;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +0900874 u8 u8mode = NO_ENCRYPT;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +0900875 u8 u8gmode = NO_ENCRYPT;
876 u8 u8pmode = NO_ENCRYPT;
Leo Kim841dfc42015-10-05 15:25:39 +0900877 enum AUTHTYPE tenuAuth_type = ANY;
Glen Lee76469202015-10-20 17:13:59 +0900878 struct wilc *wl;
Glen Leea4cac482015-12-21 14:18:36 +0900879 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900880
881 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +0900882 vif = netdev_priv(netdev);
883 wl = vif->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900884
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900885 switch (params->cipher) {
886 case WLAN_CIPHER_SUITE_WEP40:
887 case WLAN_CIPHER_SUITE_WEP104:
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900888 if (priv->wdev->iftype == NL80211_IFTYPE_AP) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900889 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
Chaehyun Limd00d2ba2015-08-10 11:33:19 +0900890 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900891
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900892 tenuAuth_type = OPEN_SYSTEM;
893
894 if (params->cipher == WLAN_CIPHER_SUITE_WEP40)
895 u8mode = ENCRYPT_ENABLED | WEP;
896 else
897 u8mode = ENCRYPT_ENABLED | WEP | WEP_EXTENDED;
898
Glen Leefbf53792015-12-21 14:18:40 +0900899 wilc_add_wep_key_bss_ap(vif, params->key,
900 params->key_len, key_index,
901 u8mode, tenuAuth_type);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900902 break;
903 }
Chaehyun Lim1a646e72015-08-07 09:02:03 +0900904 if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900905 priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
Chaehyun Limd00d2ba2015-08-10 11:33:19 +0900906 memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900907
Glen Leefbf53792015-12-21 14:18:40 +0900908 wilc_add_wep_key_bss_sta(vif, params->key,
909 params->key_len, key_index);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900910 }
911
912 break;
913
914 case WLAN_CIPHER_SUITE_TKIP:
915 case WLAN_CIPHER_SUITE_CCMP:
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900916 if (priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
Leo Kim369a1d32015-12-21 14:18:23 +0900917 if (!priv->wilc_gtk[key_index]) {
Glen Leef3052582015-09-10 12:03:04 +0900918 priv->wilc_gtk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
Greg Kroah-Hartmanb1413b62015-06-02 14:11:12 +0900919 priv->wilc_gtk[key_index]->key = NULL;
920 priv->wilc_gtk[key_index]->seq = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900921 }
Leo Kim369a1d32015-12-21 14:18:23 +0900922 if (!priv->wilc_ptk[key_index]) {
Glen Leef3052582015-09-10 12:03:04 +0900923 priv->wilc_ptk[key_index] = kmalloc(sizeof(struct wilc_wfi_key), GFP_KERNEL);
Greg Kroah-Hartmanb1413b62015-06-02 14:11:12 +0900924 priv->wilc_ptk[key_index]->key = NULL;
925 priv->wilc_ptk[key_index]->seq = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900926 }
927
928
929
Daniel Machon19132212015-08-05 08:18:31 +0200930 if (!pairwise) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900931 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
932 u8gmode = ENCRYPT_ENABLED | WPA | TKIP;
933 else
934 u8gmode = ENCRYPT_ENABLED | WPA2 | AES;
935
936 priv->wilc_groupkey = u8gmode;
937
938 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900939 pu8TxMic = params->key + 24;
940 pu8RxMic = params->key + 16;
941 KeyLen = params->key_len - 16;
942 }
Shraddha Barkecccfc392015-10-12 20:49:19 +0530943 kfree(priv->wilc_gtk[key_index]->key);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900944
Glen Leef3052582015-09-10 12:03:04 +0900945 priv->wilc_gtk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
Chaehyun Limd00d2ba2015-08-10 11:33:19 +0900946 memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
Shraddha Barkecccfc392015-10-12 20:49:19 +0530947 kfree(priv->wilc_gtk[key_index]->seq);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900948
949 if ((params->seq_len) > 0) {
Glen Leef3052582015-09-10 12:03:04 +0900950 priv->wilc_gtk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
Chaehyun Limd00d2ba2015-08-10 11:33:19 +0900951 memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900952 }
953
954 priv->wilc_gtk[key_index]->cipher = params->cipher;
955 priv->wilc_gtk[key_index]->key_len = params->key_len;
956 priv->wilc_gtk[key_index]->seq_len = params->seq_len;
957
Glen Leefbf53792015-12-21 14:18:40 +0900958 wilc_add_rx_gtk(vif, params->key, KeyLen,
959 key_index, params->seq_len,
960 params->seq, pu8RxMic,
961 pu8TxMic, AP_MODE, u8gmode);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900962
963 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900964 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
965 u8pmode = ENCRYPT_ENABLED | WPA | TKIP;
966 else
967 u8pmode = priv->wilc_groupkey | AES;
968
969
970 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900971 pu8TxMic = params->key + 24;
972 pu8RxMic = params->key + 16;
973 KeyLen = params->key_len - 16;
974 }
975
Shraddha Barkecccfc392015-10-12 20:49:19 +0530976 kfree(priv->wilc_ptk[key_index]->key);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900977
Glen Leef3052582015-09-10 12:03:04 +0900978 priv->wilc_ptk[key_index]->key = kmalloc(params->key_len, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900979
Shraddha Barkecccfc392015-10-12 20:49:19 +0530980 kfree(priv->wilc_ptk[key_index]->seq);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900981
982 if ((params->seq_len) > 0)
Glen Leef3052582015-09-10 12:03:04 +0900983 priv->wilc_ptk[key_index]->seq = kmalloc(params->seq_len, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900984
Chaehyun Limd00d2ba2015-08-10 11:33:19 +0900985 memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900986
987 if ((params->seq_len) > 0)
Chaehyun Limd00d2ba2015-08-10 11:33:19 +0900988 memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900989
990 priv->wilc_ptk[key_index]->cipher = params->cipher;
991 priv->wilc_ptk[key_index]->key_len = params->key_len;
992 priv->wilc_ptk[key_index]->seq_len = params->seq_len;
993
Glen Leefbf53792015-12-21 14:18:40 +0900994 wilc_add_ptk(vif, params->key, KeyLen,
995 mac_addr, pu8RxMic, pu8TxMic,
996 AP_MODE, u8pmode, key_index);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900997 }
998 break;
999 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001000
1001 {
1002 u8mode = 0;
Daniel Machon19132212015-08-05 08:18:31 +02001003 if (!pairwise) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001004 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001005 pu8RxMic = params->key + 24;
1006 pu8TxMic = params->key + 16;
1007 KeyLen = params->key_len - 16;
1008 }
1009
Glen Lee1f435d22015-12-21 14:18:37 +09001010 if (!g_gtk_keys_saved && netdev == wl->vif[0]->ndev) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001011 g_add_gtk_key_params.key_idx = key_index;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001012 g_add_gtk_key_params.pairwise = pairwise;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001013 if (!mac_addr) {
1014 g_add_gtk_key_params.mac_addr = NULL;
1015 } else {
Glen Leef3052582015-09-10 12:03:04 +09001016 g_add_gtk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001017 memcpy(g_add_gtk_key_params.mac_addr, mac_addr, ETH_ALEN);
1018 }
1019 g_key_gtk_params.key_len = params->key_len;
1020 g_key_gtk_params.seq_len = params->seq_len;
Glen Leef3052582015-09-10 12:03:04 +09001021 g_key_gtk_params.key = kmalloc(params->key_len, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001022 memcpy(g_key_gtk_params.key, params->key, params->key_len);
1023 if (params->seq_len > 0) {
Glen Leef3052582015-09-10 12:03:04 +09001024 g_key_gtk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001025 memcpy(g_key_gtk_params.seq, params->seq, params->seq_len);
1026 }
1027 g_key_gtk_params.cipher = params->cipher;
Dean Lee72ed4dc2015-06-12 14:11:44 +09001028 g_gtk_keys_saved = true;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001029 }
1030
Glen Leefbf53792015-12-21 14:18:40 +09001031 wilc_add_rx_gtk(vif, params->key, KeyLen,
1032 key_index, params->seq_len,
1033 params->seq, pu8RxMic,
1034 pu8TxMic, STATION_MODE,
1035 u8mode);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001036 } else {
1037 if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001038 pu8RxMic = params->key + 24;
1039 pu8TxMic = params->key + 16;
1040 KeyLen = params->key_len - 16;
1041 }
1042
Glen Lee1f435d22015-12-21 14:18:37 +09001043 if (!g_ptk_keys_saved && netdev == wl->vif[0]->ndev) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001044 g_add_ptk_key_params.key_idx = key_index;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001045 g_add_ptk_key_params.pairwise = pairwise;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001046 if (!mac_addr) {
1047 g_add_ptk_key_params.mac_addr = NULL;
1048 } else {
Glen Leef3052582015-09-10 12:03:04 +09001049 g_add_ptk_key_params.mac_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001050 memcpy(g_add_ptk_key_params.mac_addr, mac_addr, ETH_ALEN);
1051 }
1052 g_key_ptk_params.key_len = params->key_len;
1053 g_key_ptk_params.seq_len = params->seq_len;
Glen Leef3052582015-09-10 12:03:04 +09001054 g_key_ptk_params.key = kmalloc(params->key_len, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001055 memcpy(g_key_ptk_params.key, params->key, params->key_len);
1056 if (params->seq_len > 0) {
Glen Leef3052582015-09-10 12:03:04 +09001057 g_key_ptk_params.seq = kmalloc(params->seq_len, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001058 memcpy(g_key_ptk_params.seq, params->seq, params->seq_len);
1059 }
1060 g_key_ptk_params.cipher = params->cipher;
Dean Lee72ed4dc2015-06-12 14:11:44 +09001061 g_ptk_keys_saved = true;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001062 }
1063
Glen Leefbf53792015-12-21 14:18:40 +09001064 wilc_add_ptk(vif, params->key, KeyLen,
1065 mac_addr, pu8RxMic, pu8TxMic,
1066 STATION_MODE, u8mode, key_index);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001067 }
1068 }
1069 break;
1070
1071 default:
Leo Kim06fb9332016-02-04 18:15:55 +09001072 netdev_err(netdev, "Not supported cipher\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001073 s32Error = -ENOTSUPP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001074 }
1075
1076 return s32Error;
1077}
1078
Chaehyun Lim3044ba72015-09-14 12:24:06 +09001079static int del_key(struct wiphy *wiphy, struct net_device *netdev,
1080 u8 key_index,
1081 bool pairwise,
1082 const u8 *mac_addr)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001083{
Chaehyun Lim27268872015-09-15 14:06:13 +09001084 struct wilc_priv *priv;
Glen Lee692e2ac2015-10-20 17:14:00 +09001085 struct wilc *wl;
Glen Leea4cac482015-12-21 14:18:36 +09001086 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001087
1088 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +09001089 vif = netdev_priv(netdev);
1090 wl = vif->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001091
Glen Lee1f435d22015-12-21 14:18:37 +09001092 if (netdev == wl->vif[0]->ndev) {
Dean Lee72ed4dc2015-06-12 14:11:44 +09001093 g_ptk_keys_saved = false;
1094 g_gtk_keys_saved = false;
1095 g_wep_keys_saved = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001096
Shraddha Barkecccfc392015-10-12 20:49:19 +05301097 kfree(g_key_wep_params.key);
1098 g_key_wep_params.key = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001099
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001100 if ((priv->wilc_gtk[key_index]) != NULL) {
Shraddha Barkecccfc392015-10-12 20:49:19 +05301101 kfree(priv->wilc_gtk[key_index]->key);
1102 priv->wilc_gtk[key_index]->key = NULL;
1103 kfree(priv->wilc_gtk[key_index]->seq);
1104 priv->wilc_gtk[key_index]->seq = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001105
Chaehyun Lim49188af2015-08-11 10:32:41 +09001106 kfree(priv->wilc_gtk[key_index]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001107 priv->wilc_gtk[key_index] = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001108 }
1109
1110 if ((priv->wilc_ptk[key_index]) != NULL) {
Shraddha Barkecccfc392015-10-12 20:49:19 +05301111 kfree(priv->wilc_ptk[key_index]->key);
1112 priv->wilc_ptk[key_index]->key = NULL;
1113 kfree(priv->wilc_ptk[key_index]->seq);
1114 priv->wilc_ptk[key_index]->seq = NULL;
Chaehyun Lim49188af2015-08-11 10:32:41 +09001115 kfree(priv->wilc_ptk[key_index]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001116 priv->wilc_ptk[key_index] = NULL;
1117 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001118
Shraddha Barkecccfc392015-10-12 20:49:19 +05301119 kfree(g_key_ptk_params.key);
1120 g_key_ptk_params.key = NULL;
1121 kfree(g_key_ptk_params.seq);
1122 g_key_ptk_params.seq = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001123
Shraddha Barkecccfc392015-10-12 20:49:19 +05301124 kfree(g_key_gtk_params.key);
1125 g_key_gtk_params.key = NULL;
1126 kfree(g_key_gtk_params.seq);
1127 g_key_gtk_params.seq = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001128
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001129 }
1130
1131 if (key_index >= 0 && key_index <= 3) {
Leo Kimb0f18362016-04-01 17:44:19 +09001132 if (priv->WILC_WFI_wep_key_len[key_index]) {
1133 memset(priv->WILC_WFI_wep_key[key_index], 0,
1134 priv->WILC_WFI_wep_key_len[key_index]);
1135 priv->WILC_WFI_wep_key_len[key_index] = 0;
1136 wilc_remove_wep_key(vif, key_index);
1137 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001138 } else {
Leo Kim48b28df2016-02-04 18:15:32 +09001139 wilc_remove_key(priv->hif_drv, mac_addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001140 }
1141
Leo Kimaaed3292015-10-12 16:55:38 +09001142 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001143}
1144
Chaehyun Limf4893df2015-09-14 12:24:07 +09001145static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1146 bool pairwise,
1147 const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params *))
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001148{
Chaehyun Lim27268872015-09-15 14:06:13 +09001149 struct wilc_priv *priv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001150 struct key_params key_params;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001151
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001152 priv = wiphy_priv(wiphy);
1153
1154
Alison Schofield3604af52015-10-12 13:22:44 -07001155 if (!pairwise) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001156 key_params.key = priv->wilc_gtk[key_index]->key;
1157 key_params.cipher = priv->wilc_gtk[key_index]->cipher;
1158 key_params.key_len = priv->wilc_gtk[key_index]->key_len;
1159 key_params.seq = priv->wilc_gtk[key_index]->seq;
1160 key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001161 } else {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001162 key_params.key = priv->wilc_ptk[key_index]->key;
1163 key_params.cipher = priv->wilc_ptk[key_index]->cipher;
1164 key_params.key_len = priv->wilc_ptk[key_index]->key_len;
1165 key_params.seq = priv->wilc_ptk[key_index]->seq;
1166 key_params.seq_len = priv->wilc_ptk[key_index]->seq_len;
1167 }
1168
1169 callback(cookie, &key_params);
1170
Leo Kima89f7c52015-11-25 11:59:41 +09001171 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001172}
1173
Chaehyun Lim0f5b8ca2015-09-14 12:24:08 +09001174static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
1175 bool unicast, bool multicast)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001176{
Chaehyun Lim27268872015-09-15 14:06:13 +09001177 struct wilc_priv *priv;
Glen Leecf601062015-12-21 14:18:39 +09001178 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001179
1180 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +09001181 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001182
Glen Leeec450482016-02-04 18:15:28 +09001183 wilc_set_wep_default_keyid(vif, key_index);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001184
Leo Kimaaed3292015-10-12 16:55:38 +09001185 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001186}
1187
Chaehyun Limf06f5622015-09-14 12:24:18 +09001188static int get_station(struct wiphy *wiphy, struct net_device *dev,
1189 const u8 *mac, struct station_info *sinfo)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001190{
Chaehyun Lim27268872015-09-15 14:06:13 +09001191 struct wilc_priv *priv;
Glen Leea4cac482015-12-21 14:18:36 +09001192 struct wilc_vif *vif;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001193 u32 i = 0;
Colin Ian King6c08fda2016-08-15 17:09:52 +01001194 u32 associatedsta = ~0;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001195 u32 inactive_time = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001196 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +09001197 vif = netdev_priv(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001198
Glen Leea4cac482015-12-21 14:18:36 +09001199 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001200 for (i = 0; i < NUM_STA_ASSOCIATED; i++) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001201 if (!(memcmp(mac, priv->assoc_stainfo.au8Sta_AssociatedBss[i], ETH_ALEN))) {
1202 associatedsta = i;
1203 break;
1204 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001205 }
1206
Colin Ian King6c08fda2016-08-15 17:09:52 +01001207 if (associatedsta == ~0) {
Leo Kim06fb9332016-02-04 18:15:55 +09001208 netdev_err(dev, "sta required is not associated\n");
Leo Kimaaed3292015-10-12 16:55:38 +09001209 return -ENOENT;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001210 }
1211
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001212 sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001213
Glen Leefbf53792015-12-21 14:18:40 +09001214 wilc_get_inactive_time(vif, mac, &inactive_time);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001215 sinfo->inactive_time = 1000 * inactive_time;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001216 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001217
Glen Leea4cac482015-12-21 14:18:36 +09001218 if (vif->iftype == STATION_MODE) {
Leo Kim03e7b9c2015-10-12 16:55:58 +09001219 struct rf_info strStatistics;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001220
Glen Leefbf53792015-12-21 14:18:40 +09001221 wilc_get_statistics(vif, &strStatistics);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001222
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001223 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
Chandra S Gorentla62129902015-08-05 22:11:57 +05301224 BIT(NL80211_STA_INFO_RX_PACKETS) |
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001225 BIT(NL80211_STA_INFO_TX_PACKETS) |
1226 BIT(NL80211_STA_INFO_TX_FAILED) |
1227 BIT(NL80211_STA_INFO_TX_BITRATE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001228
Leo Kim00c8dfc2015-10-29 12:05:30 +09001229 sinfo->signal = strStatistics.rssi;
Leo Kim9b992742015-10-29 12:05:32 +09001230 sinfo->rx_packets = strStatistics.rx_cnt;
Leo Kim54160372015-10-29 12:05:33 +09001231 sinfo->tx_packets = strStatistics.tx_cnt + strStatistics.tx_fail_cnt;
1232 sinfo->tx_failed = strStatistics.tx_fail_cnt;
Leo Kim5babeec2015-10-29 12:05:29 +09001233 sinfo->txrate.legacy = strStatistics.link_speed * 10;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001234
Leo Kim5babeec2015-10-29 12:05:29 +09001235 if ((strStatistics.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH) &&
1236 (strStatistics.link_speed != DEFAULT_LINK_SPEED))
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001237 wilc_enable_tcp_ack_filter(true);
Leo Kim5babeec2015-10-29 12:05:29 +09001238 else if (strStatistics.link_speed != DEFAULT_LINK_SPEED)
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001239 wilc_enable_tcp_ack_filter(false);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001240 }
Leo Kimaaed3292015-10-12 16:55:38 +09001241 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001242}
1243
Chaehyun Lima5f7db62015-09-14 12:24:20 +09001244static int change_bss(struct wiphy *wiphy, struct net_device *dev,
1245 struct bss_parameters *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001246{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001247 return 0;
1248}
1249
Chaehyun Lima76b63e2015-09-14 12:24:21 +09001250static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001251{
Leo Kime6e12662015-09-16 18:36:03 +09001252 s32 s32Error = 0;
Chaehyun Lima5f0fb52016-02-23 15:37:58 +09001253 struct cfg_param_attr pstrCfgParamVal;
Chaehyun Lim27268872015-09-15 14:06:13 +09001254 struct wilc_priv *priv;
Glen Leecf601062015-12-21 14:18:39 +09001255 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001256
1257 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +09001258 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001259
Tony Cho87c05b22015-10-12 16:56:07 +09001260 pstrCfgParamVal.flag = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001261
1262 if (changed & WIPHY_PARAM_RETRY_SHORT) {
Tony Cho87c05b22015-10-12 16:56:07 +09001263 pstrCfgParamVal.flag |= RETRY_SHORT;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001264 pstrCfgParamVal.short_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_short;
1265 }
1266 if (changed & WIPHY_PARAM_RETRY_LONG) {
Tony Cho87c05b22015-10-12 16:56:07 +09001267 pstrCfgParamVal.flag |= RETRY_LONG;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001268 pstrCfgParamVal.long_retry_limit = priv->dev->ieee80211_ptr->wiphy->retry_long;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001269 }
1270 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
Tony Cho87c05b22015-10-12 16:56:07 +09001271 pstrCfgParamVal.flag |= FRAG_THRESHOLD;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001272 pstrCfgParamVal.frag_threshold = priv->dev->ieee80211_ptr->wiphy->frag_threshold;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001273 }
1274
1275 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
Tony Cho87c05b22015-10-12 16:56:07 +09001276 pstrCfgParamVal.flag |= RTS_THRESHOLD;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001277 pstrCfgParamVal.rts_threshold = priv->dev->ieee80211_ptr->wiphy->rts_threshold;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001278 }
1279
Glen Leefbf53792015-12-21 14:18:40 +09001280 s32Error = wilc_hif_set_cfg(vif, &pstrCfgParamVal);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001281 if (s32Error)
Leo Kim06fb9332016-02-04 18:15:55 +09001282 netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001283
1284 return s32Error;
1285}
Arnd Bergmanne5af0562015-05-29 22:52:12 +02001286
Chaehyun Lim4d466572015-09-14 12:24:22 +09001287static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1288 struct cfg80211_pmksa *pmksa)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001289{
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001290 u32 i;
Leo Kime6e12662015-09-16 18:36:03 +09001291 s32 s32Error = 0;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +09001292 u8 flag = 0;
Glen Leecf601062015-12-21 14:18:39 +09001293 struct wilc_vif *vif;
Chaehyun Lim27268872015-09-15 14:06:13 +09001294 struct wilc_priv *priv = wiphy_priv(wiphy);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001295
Glen Leecf601062015-12-21 14:18:39 +09001296 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001297
1298
1299 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
Chaehyun Lim1a646e72015-08-07 09:02:03 +09001300 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001301 ETH_ALEN)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001302 flag = PMKID_FOUND;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001303 break;
1304 }
1305 }
1306 if (i < WILC_MAX_NUM_PMKIDS) {
Chaehyun Limd00d2ba2015-08-10 11:33:19 +09001307 memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001308 ETH_ALEN);
Chaehyun Limd00d2ba2015-08-10 11:33:19 +09001309 memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001310 PMKID_LEN);
1311 if (!(flag == PMKID_FOUND))
1312 priv->pmkid_list.numpmkid++;
1313 } else {
Leo Kim06fb9332016-02-04 18:15:55 +09001314 netdev_err(netdev, "Invalid PMKID index\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001315 s32Error = -EINVAL;
1316 }
1317
Chris Park64d35462016-02-22 13:11:57 +09001318 if (!s32Error)
Glen Leefbf53792015-12-21 14:18:40 +09001319 s32Error = wilc_set_pmkid_info(vif, &priv->pmkid_list);
Chris Park64d35462016-02-22 13:11:57 +09001320
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001321 return s32Error;
1322}
1323
Chaehyun Lim1ff86d92015-09-14 12:24:23 +09001324static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1325 struct cfg80211_pmksa *pmksa)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001326{
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001327 u32 i;
Leo Kime6e12662015-09-16 18:36:03 +09001328 s32 s32Error = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001329
Chaehyun Lim27268872015-09-15 14:06:13 +09001330 struct wilc_priv *priv = wiphy_priv(wiphy);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001331
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001332 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
Chaehyun Lim1a646e72015-08-07 09:02:03 +09001333 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001334 ETH_ALEN)) {
Leo Kimcd1e6cb2015-10-05 15:25:45 +09001335 memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(struct host_if_pmkid));
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001336 break;
1337 }
1338 }
1339
1340 if (i < priv->pmkid_list.numpmkid && priv->pmkid_list.numpmkid > 0) {
1341 for (; i < (priv->pmkid_list.numpmkid - 1); i++) {
Chaehyun Limd00d2ba2015-08-10 11:33:19 +09001342 memcpy(priv->pmkid_list.pmkidlist[i].bssid,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001343 priv->pmkid_list.pmkidlist[i + 1].bssid,
1344 ETH_ALEN);
Chaehyun Limd00d2ba2015-08-10 11:33:19 +09001345 memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001346 priv->pmkid_list.pmkidlist[i].pmkid,
1347 PMKID_LEN);
1348 }
1349 priv->pmkid_list.numpmkid--;
1350 } else {
1351 s32Error = -EINVAL;
1352 }
1353
1354 return s32Error;
1355}
1356
Chaehyun Limb33c39b2015-09-14 12:24:24 +09001357static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001358{
Chaehyun Lim27268872015-09-15 14:06:13 +09001359 struct wilc_priv *priv = wiphy_priv(wiphy);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001360
Leo Kima949f902015-10-05 15:25:44 +09001361 memset(&priv->pmkid_list, 0, sizeof(struct host_if_pmkid_attr));
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001362
1363 return 0;
1364}
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001365
Arnd Bergmann1608c402015-11-16 15:04:53 +01001366static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001367{
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001368 u32 index = 0;
1369 u32 i = 0, j = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001370
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +09001371 u8 op_channel_attr_index = 0;
1372 u8 channel_list_attr_index = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001373
1374 while (index < len) {
Roger H. Newelld5e27e82016-03-19 12:49:21 -02301375 if (buf[index] == GO_INTENT_ATTR_ID)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001376 buf[index + 3] = (buf[index + 3] & 0x01) | (0x00 << 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001377
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301378 if (buf[index] == CHANLIST_ATTR_ID)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001379 channel_list_attr_index = index;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301380 else if (buf[index] == OPERCHAN_ATTR_ID)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001381 op_channel_attr_index = index;
Leo Kima89f7c52015-11-25 11:59:41 +09001382 index += buf[index + 1] + 3;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001383 }
Leo Kim0bd82742015-11-19 15:56:14 +09001384 if (wlan_channel != INVALID_CHANNEL) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001385 if (channel_list_attr_index) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001386 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
1387 if (buf[i] == 0x51) {
Roger H. Newelld5e27e82016-03-19 12:49:21 -02301388 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++)
Leo Kim0bd82742015-11-19 15:56:14 +09001389 buf[j] = wlan_channel;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001390 break;
1391 }
1392 }
1393 }
Leo Kima89f7c52015-11-25 11:59:41 +09001394
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001395 if (op_channel_attr_index) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001396 buf[op_channel_attr_index + 6] = 0x51;
Leo Kim0bd82742015-11-19 15:56:14 +09001397 buf[op_channel_attr_index + 7] = wlan_channel;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001398 }
1399 }
1400}
1401
Arnd Bergmann1608c402015-11-16 15:04:53 +01001402static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftype)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001403{
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001404 u32 index = 0;
1405 u32 i = 0, j = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001406
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +09001407 u8 op_channel_attr_index = 0;
1408 u8 channel_list_attr_index = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001409
1410 while (index < len) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001411 if (buf[index] == GO_INTENT_ATTR_ID) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001412 buf[index + 3] = (buf[index + 3] & 0x01) | (0x0f << 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001413
1414 break;
1415 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001416
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301417 if (buf[index] == CHANLIST_ATTR_ID)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001418 channel_list_attr_index = index;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +05301419 else if (buf[index] == OPERCHAN_ATTR_ID)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001420 op_channel_attr_index = index;
Leo Kima89f7c52015-11-25 11:59:41 +09001421 index += buf[index + 1] + 3;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001422 }
Leo Kim0bd82742015-11-19 15:56:14 +09001423 if (wlan_channel != INVALID_CHANNEL && bOperChan) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001424 if (channel_list_attr_index) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001425 for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
1426 if (buf[i] == 0x51) {
Roger H. Newelld5e27e82016-03-19 12:49:21 -02301427 for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++)
Leo Kim0bd82742015-11-19 15:56:14 +09001428 buf[j] = wlan_channel;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001429 break;
1430 }
1431 }
1432 }
Leo Kima89f7c52015-11-25 11:59:41 +09001433
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001434 if (op_channel_attr_index) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001435 buf[op_channel_attr_index + 6] = 0x51;
Leo Kim0bd82742015-11-19 15:56:14 +09001436 buf[op_channel_attr_index + 7] = wlan_channel;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001437 }
1438 }
1439}
1440
Anchal Jain63f80352016-03-02 21:12:19 +05301441void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001442{
Chaehyun Lim27268872015-09-15 14:06:13 +09001443 struct wilc_priv *priv;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001444 u32 header, pkt_offset;
Leo Kim441dc602015-10-12 16:55:35 +09001445 struct host_if_drv *pstrWFIDrv;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001446 u32 i = 0;
Chaehyun Limfb4ec9c2015-06-11 14:35:59 +09001447 s32 s32Freq;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001448
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001449 priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
Leo Kim48b28df2016-02-04 18:15:32 +09001450 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001451
Chaehyun Limd00d2ba2015-08-10 11:33:19 +09001452 memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001453
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001454 pkt_offset = GET_PKT_OFFSET(header);
1455
1456 if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
1457 if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001458 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001459 return;
1460 } else {
Chris Parke3f16962016-02-04 18:24:30 +09001461 if (pkt_offset & IS_MGMT_STATUS_SUCCES)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001462 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
Chris Parke3f16962016-02-04 18:24:30 +09001463 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001464 cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001465 return;
1466 }
1467 } else {
Johannes Berg57fbcce2016-04-12 15:56:15 +02001468 s32Freq = ieee80211_channel_to_frequency(curr_channel, NL80211_BAND_2GHZ);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001469
1470 if (ieee80211_is_action(buff[FRAME_TYPE_ID])) {
Leo Kim1229b1a2015-10-29 12:05:39 +09001471 if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) {
Chris Parke3f16962016-02-04 18:24:30 +09001472 netdev_dbg(dev, "Receiving action wrong ch\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001473 return;
1474 }
1475 if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001476 switch (buff[ACTION_SUBTYPE_ID]) {
1477 case GAS_INTIAL_REQ:
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001478 break;
1479
1480 case GAS_INTIAL_RSP:
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001481 break;
1482
1483 case PUBLIC_ACT_VENDORSPEC:
Leo Kim881eb5d2015-11-19 15:56:15 +09001484 if (!memcmp(p2p_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001485 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
Leo Kima25d5182015-11-19 15:56:19 +09001486 if (!wilc_ie) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001487 for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) {
Leo Kim86685942015-11-19 15:56:18 +09001488 if (!memcmp(p2p_vendor_spec, &buff[i], 6)) {
Leo Kimb84a3ac2015-11-19 15:56:17 +09001489 p2p_recv_random = buff[i + 6];
Leo Kima25d5182015-11-19 15:56:19 +09001490 wilc_ie = true;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001491 break;
1492 }
1493 }
1494 }
1495 }
Leo Kimb84a3ac2015-11-19 15:56:17 +09001496 if (p2p_local_random > p2p_recv_random) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001497 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
1498 || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
1499 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
Leo Kim881eb5d2015-11-19 15:56:15 +09001500 if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buff[i + 2], 4))) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001501 WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6));
1502 break;
1503 }
1504 }
1505 }
Leo Kim583d9722015-11-19 15:56:16 +09001506 } else {
Chris Parke3f16962016-02-04 18:24:30 +09001507 netdev_dbg(dev, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
Leo Kim583d9722015-11-19 15:56:16 +09001508 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001509 }
1510
1511
Leo Kima25d5182015-11-19 15:56:19 +09001512 if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (wilc_ie)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001513 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001514 return;
1515 }
1516 break;
1517
1518 default:
Chris Parke3f16962016-02-04 18:24:30 +09001519 netdev_dbg(dev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001520 break;
1521 }
1522 }
1523 }
1524
Glen Lee783d07c2016-02-04 18:15:26 +09001525 cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001526 }
1527}
1528
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001529static void WILC_WFI_mgmt_tx_complete(void *priv, int status)
1530{
Alison Schofield4375cad2016-02-12 22:54:08 -08001531 struct p2p_mgmt_data *pv_data = priv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001532
1533
1534 kfree(pv_data->buff);
1535 kfree(pv_data);
1536}
1537
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001538static void WILC_WFI_RemainOnChannelReady(void *pUserVoid)
1539{
Chaehyun Lim27268872015-09-15 14:06:13 +09001540 struct wilc_priv *priv;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001541
Alison Schofield4375cad2016-02-12 22:54:08 -08001542 priv = pUserVoid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001543
Dean Lee72ed4dc2015-06-12 14:11:44 +09001544 priv->bInP2PlistenState = true;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001545
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001546 cfg80211_ready_on_channel(priv->wdev,
1547 priv->strRemainOnChanParams.u64ListenCookie,
1548 priv->strRemainOnChanParams.pstrListenChan,
1549 priv->strRemainOnChanParams.u32ListenDuration,
1550 GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001551}
1552
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001553static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001554{
Chaehyun Lim27268872015-09-15 14:06:13 +09001555 struct wilc_priv *priv;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001556
Alison Schofield4375cad2016-02-12 22:54:08 -08001557 priv = pUserVoid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001558
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001559 if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
Dean Lee72ed4dc2015-06-12 14:11:44 +09001560 priv->bInP2PlistenState = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001561
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001562 cfg80211_remain_on_channel_expired(priv->wdev,
1563 priv->strRemainOnChanParams.u64ListenCookie,
1564 priv->strRemainOnChanParams.pstrListenChan,
1565 GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001566 }
1567}
1568
Chaehyun Lim6d19d692015-09-14 12:24:25 +09001569static int remain_on_channel(struct wiphy *wiphy,
1570 struct wireless_dev *wdev,
1571 struct ieee80211_channel *chan,
1572 unsigned int duration, u64 *cookie)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001573{
Leo Kime6e12662015-09-16 18:36:03 +09001574 s32 s32Error = 0;
Chaehyun Lim27268872015-09-15 14:06:13 +09001575 struct wilc_priv *priv;
Glen Leecf601062015-12-21 14:18:39 +09001576 struct wilc_vif *vif;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001577
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001578 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +09001579 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001580
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001581 if (wdev->iftype == NL80211_IFTYPE_AP) {
Chris Parke3f16962016-02-04 18:24:30 +09001582 netdev_dbg(vif->ndev, "Required while in AP mode\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001583 return s32Error;
1584 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001585
Chaehyun Lim866a2c22015-10-02 16:41:21 +09001586 curr_channel = chan->hw_value;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001587
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001588 priv->strRemainOnChanParams.pstrListenChan = chan;
1589 priv->strRemainOnChanParams.u64ListenCookie = *cookie;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001590 priv->strRemainOnChanParams.u32ListenDuration = duration;
1591 priv->strRemainOnChanParams.u32ListenSessionID++;
1592
Glen Leefbf53792015-12-21 14:18:40 +09001593 s32Error = wilc_remain_on_channel(vif,
1594 priv->strRemainOnChanParams.u32ListenSessionID,
1595 duration, chan->hw_value,
1596 WILC_WFI_RemainOnChannelExpired,
1597 WILC_WFI_RemainOnChannelReady, (void *)priv);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001598
1599 return s32Error;
1600}
1601
Chaehyun Lim1dd54402015-09-14 12:24:26 +09001602static int cancel_remain_on_channel(struct wiphy *wiphy,
1603 struct wireless_dev *wdev,
1604 u64 cookie)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001605{
Leo Kime6e12662015-09-16 18:36:03 +09001606 s32 s32Error = 0;
Chaehyun Lim27268872015-09-15 14:06:13 +09001607 struct wilc_priv *priv;
Glen Leecf601062015-12-21 14:18:39 +09001608 struct wilc_vif *vif;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001609
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001610 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +09001611 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001612
Glen Leefbf53792015-12-21 14:18:40 +09001613 s32Error = wilc_listen_state_expired(vif, priv->strRemainOnChanParams.u32ListenSessionID);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001614 return s32Error;
1615}
Leo Kima89f7c52015-11-25 11:59:41 +09001616
Chaehyun Limc1560322015-09-22 18:34:51 +09001617static int mgmt_tx(struct wiphy *wiphy,
1618 struct wireless_dev *wdev,
1619 struct cfg80211_mgmt_tx_params *params,
1620 u64 *cookie)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001621{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001622 struct ieee80211_channel *chan = params->chan;
1623 unsigned int wait = params->wait;
1624 const u8 *buf = params->buf;
1625 size_t len = params->len;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001626 const struct ieee80211_mgmt *mgmt;
1627 struct p2p_mgmt_data *mgmt_tx;
Chaehyun Lim27268872015-09-15 14:06:13 +09001628 struct wilc_priv *priv;
Leo Kim441dc602015-10-12 16:55:35 +09001629 struct host_if_drv *pstrWFIDrv;
Chaehyun Lim4e4467f2015-06-11 14:35:55 +09001630 u32 i;
Glen Leea4cac482015-12-21 14:18:36 +09001631 struct wilc_vif *vif;
Leo Kim86685942015-11-19 15:56:18 +09001632 u32 buf_len = len + sizeof(p2p_vendor_spec) + sizeof(p2p_local_random);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001633
Glen Leea4cac482015-12-21 14:18:36 +09001634 vif = netdev_priv(wdev->netdev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001635 priv = wiphy_priv(wiphy);
Leo Kim48b28df2016-02-04 18:15:32 +09001636 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001637
1638 *cookie = (unsigned long)buf;
1639 priv->u64tx_cookie = *cookie;
1640 mgmt = (const struct ieee80211_mgmt *) buf;
1641
1642 if (ieee80211_is_mgmt(mgmt->frame_control)) {
Glen Leef3052582015-09-10 12:03:04 +09001643 mgmt_tx = kmalloc(sizeof(struct p2p_mgmt_data), GFP_KERNEL);
Leo Kim06fb9332016-02-04 18:15:55 +09001644 if (!mgmt_tx)
Leo Kime6e12662015-09-16 18:36:03 +09001645 return -EFAULT;
Leo Kim06fb9332016-02-04 18:15:55 +09001646
Glen Leef3052582015-09-10 12:03:04 +09001647 mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL);
Dan Carpenterd99ee282016-02-10 12:05:40 +03001648 if (!mgmt_tx->buff) {
Tony Chof638dd32015-09-07 19:09:31 +09001649 kfree(mgmt_tx);
Dan Carpenterd99ee282016-02-10 12:05:40 +03001650 return -ENOMEM;
1651 }
Leo Kim06fb9332016-02-04 18:15:55 +09001652
Chaehyun Limd00d2ba2015-08-10 11:33:19 +09001653 memcpy(mgmt_tx->buff, buf, len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001654 mgmt_tx->size = len;
1655
1656
1657 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
Glen Leefbf53792015-12-21 14:18:40 +09001658 wilc_set_mac_chnl_num(vif, chan->hw_value);
Chaehyun Lim866a2c22015-10-02 16:41:21 +09001659 curr_channel = chan->hw_value;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001660 } else if (ieee80211_is_action(mgmt->frame_control)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001661 if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001662 if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC ||
1663 buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) {
Glen Leefbf53792015-12-21 14:18:40 +09001664 wilc_set_mac_chnl_num(vif,
1665 chan->hw_value);
Chaehyun Lim866a2c22015-10-02 16:41:21 +09001666 curr_channel = chan->hw_value;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001667 }
1668 switch (buf[ACTION_SUBTYPE_ID]) {
1669 case GAS_INTIAL_REQ:
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001670 break;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001671
1672 case GAS_INTIAL_RSP:
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001673 break;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001674
1675 case PUBLIC_ACT_VENDORSPEC:
1676 {
Leo Kim881eb5d2015-11-19 15:56:15 +09001677 if (!memcmp(p2p_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001678 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
Leo Kimb84a3ac2015-11-19 15:56:17 +09001679 if (p2p_local_random == 1 && p2p_recv_random < p2p_local_random) {
Leo Kim583d9722015-11-19 15:56:16 +09001680 get_random_bytes(&p2p_local_random, 1);
1681 p2p_local_random++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001682 }
1683 }
1684
1685 if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
1686 || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
Leo Kimb84a3ac2015-11-19 15:56:17 +09001687 if (p2p_local_random > p2p_recv_random) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001688 for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
Leo Kim881eb5d2015-11-19 15:56:15 +09001689 if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buf[i + 2], 4))) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001690 if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
Glen Leea4cac482015-12-21 14:18:36 +09001691 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, vif->iftype);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001692 else
Glen Leea4cac482015-12-21 14:18:36 +09001693 WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), false, vif->iftype);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001694 break;
1695 }
1696 }
1697
1698 if (buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_REQ && buf[P2P_PUB_ACTION_SUBTYPE] != P2P_INV_RSP) {
Leo Kim86685942015-11-19 15:56:18 +09001699 memcpy(&mgmt_tx->buff[len], p2p_vendor_spec, sizeof(p2p_vendor_spec));
1700 mgmt_tx->buff[len + sizeof(p2p_vendor_spec)] = p2p_local_random;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001701 mgmt_tx->size = buf_len;
1702 }
Leo Kim583d9722015-11-19 15:56:16 +09001703 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001704 }
1705
1706 } else {
Chris Parke3f16962016-02-04 18:24:30 +09001707 netdev_dbg(vif->ndev, "Not a P2P public action frame\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001708 }
1709
1710 break;
1711 }
1712
1713 default:
1714 {
Chris Parke3f16962016-02-04 18:24:30 +09001715 netdev_dbg(vif->ndev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001716 break;
1717 }
1718 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001719 }
1720
Leo Kim1229b1a2015-10-29 12:05:39 +09001721 pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001722 }
1723
Glen Lee829c4772015-10-29 12:18:44 +09001724 wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,
1725 mgmt_tx->buff, mgmt_tx->size,
Glen Leec9d48342015-10-01 16:03:43 +09001726 WILC_WFI_mgmt_tx_complete);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001727 }
Leo Kimaaed3292015-10-12 16:55:38 +09001728 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001729}
1730
Chaehyun Lim85c587a2015-09-22 18:34:50 +09001731static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
1732 struct wireless_dev *wdev,
1733 u64 cookie)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001734{
Chaehyun Lim27268872015-09-15 14:06:13 +09001735 struct wilc_priv *priv;
Leo Kim441dc602015-10-12 16:55:35 +09001736 struct host_if_drv *pstrWFIDrv;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001737
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001738 priv = wiphy_priv(wiphy);
Leo Kim48b28df2016-02-04 18:15:32 +09001739 pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
Leo Kim1229b1a2015-10-29 12:05:39 +09001740 pstrWFIDrv->p2p_timeout = jiffies;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001741
Luis de Bethencourt7e4e87d2015-10-16 16:32:26 +01001742 if (!priv->bInP2PlistenState) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001743 cfg80211_remain_on_channel_expired(priv->wdev,
1744 priv->strRemainOnChanParams.u64ListenCookie,
1745 priv->strRemainOnChanParams.pstrListenChan,
1746 GFP_KERNEL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001747 }
1748
1749 return 0;
1750}
1751
Chaehyun Lim8e0735c2015-09-20 15:51:16 +09001752void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
1753 u16 frame_type, bool reg)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001754{
Chaehyun Lim27268872015-09-15 14:06:13 +09001755 struct wilc_priv *priv;
Glen Leea4cac482015-12-21 14:18:36 +09001756 struct wilc_vif *vif;
Glen Lee1b869352015-10-20 17:14:01 +09001757 struct wilc *wl;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001758
1759 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +09001760 vif = netdev_priv(priv->wdev->netdev);
1761 wl = vif->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001762
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001763 if (!frame_type)
1764 return;
1765
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001766 switch (frame_type) {
1767 case PROBE_REQ:
1768 {
Leo Kim340a84f2016-03-25 21:16:50 +09001769 vif->frame_reg[0].type = frame_type;
Leo Kim89febb22016-03-25 21:16:49 +09001770 vif->frame_reg[0].reg = reg;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001771 }
1772 break;
1773
1774 case ACTION:
1775 {
Leo Kim340a84f2016-03-25 21:16:50 +09001776 vif->frame_reg[1].type = frame_type;
Leo Kim89febb22016-03-25 21:16:49 +09001777 vif->frame_reg[1].reg = reg;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001778 }
1779 break;
1780
1781 default:
1782 {
1783 break;
1784 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001785 }
Leo Kima89f7c52015-11-25 11:59:41 +09001786
Chris Parke3f16962016-02-04 18:24:30 +09001787 if (!wl->initialized)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001788 return;
Glen Leefbf53792015-12-21 14:18:40 +09001789 wilc_frame_register(vif, frame_type, reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001790}
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001791
Chaehyun Lima8047e22015-09-22 18:34:48 +09001792static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
1793 s32 rssi_thold, u32 rssi_hyst)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001794{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001795 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001796}
Leo Kima89f7c52015-11-25 11:59:41 +09001797
Chaehyun Limbdb63382015-09-14 12:24:19 +09001798static int dump_station(struct wiphy *wiphy, struct net_device *dev,
1799 int idx, u8 *mac, struct station_info *sinfo)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001800{
Chaehyun Lim27268872015-09-15 14:06:13 +09001801 struct wilc_priv *priv;
Glen Leecf601062015-12-21 14:18:39 +09001802 struct wilc_vif *vif;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001803
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001804 if (idx != 0)
1805 return -ENOENT;
1806
1807 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +09001808 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001809
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001810 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001811
Glen Leefbf53792015-12-21 14:18:40 +09001812 wilc_get_rssi(vif, &sinfo->signal);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001813
Kangjie Lud1382962016-05-03 21:36:11 -04001814 memcpy(mac, priv->au8AssociatedBss, ETH_ALEN);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001815 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001816}
1817
Chaehyun Lim46530672015-09-22 18:34:46 +09001818static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1819 bool enabled, int timeout)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001820{
Chaehyun Lim27268872015-09-15 14:06:13 +09001821 struct wilc_priv *priv;
Glen Leecf601062015-12-21 14:18:39 +09001822 struct wilc_vif *vif;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001823
Leo Kim369a1d32015-12-21 14:18:23 +09001824 if (!wiphy)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001825 return -ENOENT;
1826
1827 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +09001828 vif = netdev_priv(priv->dev);
Leo Kim06fb9332016-02-04 18:15:55 +09001829 if (!priv->hif_drv)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001830 return -EIO;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001831
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001832 if (wilc_enable_ps)
Glen Leefbf53792015-12-21 14:18:40 +09001833 wilc_set_power_mgmt(vif, enabled, timeout);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001834
1835
Leo Kime6e12662015-09-16 18:36:03 +09001836 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001837}
Glen Lee108b3432015-09-16 18:53:20 +09001838
Chaehyun Lim3615e9a2015-09-14 12:24:11 +09001839static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
1840 enum nl80211_iftype type, u32 *flags, struct vif_params *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001841{
Chaehyun Lim27268872015-09-15 14:06:13 +09001842 struct wilc_priv *priv;
Glen Leea4cac482015-12-21 14:18:36 +09001843 struct wilc_vif *vif;
Glen Lee299382c2015-10-20 17:13:56 +09001844 struct wilc *wl;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001845
Glen Leea4cac482015-12-21 14:18:36 +09001846 vif = netdev_priv(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001847 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +09001848 wl = vif->wilc;
Leo Kim583d9722015-11-19 15:56:16 +09001849 p2p_local_random = 0x01;
Leo Kimb84a3ac2015-11-19 15:56:17 +09001850 p2p_recv_random = 0x00;
Leo Kima25d5182015-11-19 15:56:19 +09001851 wilc_ie = false;
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001852 wilc_optaining_ip = false;
1853 del_timer(&wilc_during_ip_timer);
Leo Kima89f7c52015-11-25 11:59:41 +09001854
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001855 switch (type) {
1856 case NL80211_IFTYPE_STATION:
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001857 wilc_connecting = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001858 dev->ieee80211_ptr->iftype = type;
1859 priv->wdev->iftype = type;
Glen Leea4cac482015-12-21 14:18:36 +09001860 vif->monitor_flag = 0;
1861 vif->iftype = STATION_MODE;
Glen Lee86bff012016-01-25 16:35:17 +09001862 wilc_set_operation_mode(vif, STATION_MODE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001863
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001864 memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001865
Glen Lee86bff012016-01-25 16:35:17 +09001866 wilc_enable_ps = true;
1867 wilc_set_power_mgmt(vif, 1, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001868 break;
1869
1870 case NL80211_IFTYPE_P2P_CLIENT:
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001871 wilc_connecting = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001872 dev->ieee80211_ptr->iftype = type;
1873 priv->wdev->iftype = type;
Glen Leea4cac482015-12-21 14:18:36 +09001874 vif->monitor_flag = 0;
Glen Leea4cac482015-12-21 14:18:36 +09001875 vif->iftype = CLIENT_MODE;
Glen Lee86bff012016-01-25 16:35:17 +09001876 wilc_set_operation_mode(vif, STATION_MODE);
Glen Leeee632302016-01-25 16:35:18 +09001877
1878 wilc_enable_ps = false;
1879 wilc_set_power_mgmt(vif, 0, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001880 break;
1881
1882 case NL80211_IFTYPE_AP:
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001883 wilc_enable_ps = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001884 dev->ieee80211_ptr->iftype = type;
1885 priv->wdev->iftype = type;
Glen Leea4cac482015-12-21 14:18:36 +09001886 vif->iftype = AP_MODE;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001887
Glen Lee86bff012016-01-25 16:35:17 +09001888 if (wl->initialized) {
Glen Leeb3306862016-02-04 18:15:18 +09001889 wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
1890 0);
Glen Lee86bff012016-01-25 16:35:17 +09001891 wilc_set_operation_mode(vif, AP_MODE);
1892 wilc_set_power_mgmt(vif, 0, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001893 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001894 break;
1895
1896 case NL80211_IFTYPE_P2P_GO:
Arnd Bergmann0e1af732015-11-16 15:04:54 +01001897 wilc_optaining_ip = true;
Leo Kim7e872df2015-11-19 15:56:20 +09001898 mod_timer(&wilc_during_ip_timer,
1899 jiffies + msecs_to_jiffies(during_ip_time));
Glen Lee86bff012016-01-25 16:35:17 +09001900 wilc_set_operation_mode(vif, AP_MODE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001901 dev->ieee80211_ptr->iftype = type;
1902 priv->wdev->iftype = type;
Glen Leea4cac482015-12-21 14:18:36 +09001903 vif->iftype = GO_MODE;
Glen Leeee632302016-01-25 16:35:18 +09001904
1905 wilc_enable_ps = false;
1906 wilc_set_power_mgmt(vif, 0, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001907 break;
1908
1909 default:
Leo Kim06fb9332016-02-04 18:15:55 +09001910 netdev_err(dev, "Unknown interface type= %d\n", type);
Leo Kimaaed3292015-10-12 16:55:38 +09001911 return -EINVAL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001912 }
1913
Leo Kimaaed3292015-10-12 16:55:38 +09001914 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001915}
1916
Chaehyun Lima13168d2015-09-14 12:24:12 +09001917static int start_ap(struct wiphy *wiphy, struct net_device *dev,
1918 struct cfg80211_ap_settings *settings)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001919{
1920 struct cfg80211_beacon_data *beacon = &(settings->beacon);
Chaehyun Lim27268872015-09-15 14:06:13 +09001921 struct wilc_priv *priv;
Leo Kime6e12662015-09-16 18:36:03 +09001922 s32 s32Error = 0;
Glen Lee684dc182015-10-20 17:14:02 +09001923 struct wilc *wl;
Glen Leea4cac482015-12-21 14:18:36 +09001924 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001925
1926 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +09001927 vif = netdev_priv(dev);
Leo Kim79f7dfa2016-02-23 21:10:54 +09001928 wl = vif->wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001929
Chaehyun Lim80785a92015-09-14 12:24:01 +09001930 s32Error = set_channel(wiphy, &settings->chandef);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001931
Leo Kime6e12662015-09-16 18:36:03 +09001932 if (s32Error != 0)
Leo Kim06fb9332016-02-04 18:15:55 +09001933 netdev_err(dev, "Error in setting channel\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001934
Leo Kim67501402016-02-04 18:15:39 +09001935 wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE);
Glen Leecba352a2016-02-04 18:15:25 +09001936 wilc_set_power_mgmt(vif, 0, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001937
Glen Leefbf53792015-12-21 14:18:40 +09001938 s32Error = wilc_add_beacon(vif, settings->beacon_interval,
1939 settings->dtim_period, beacon->head_len,
1940 (u8 *)beacon->head, beacon->tail_len,
1941 (u8 *)beacon->tail);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001942
1943 return s32Error;
1944}
1945
Chaehyun Lim2a4c84d2015-09-14 12:24:13 +09001946static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
1947 struct cfg80211_beacon_data *beacon)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001948{
Chaehyun Lim27268872015-09-15 14:06:13 +09001949 struct wilc_priv *priv;
Glen Leecf601062015-12-21 14:18:39 +09001950 struct wilc_vif *vif;
Leo Kime6e12662015-09-16 18:36:03 +09001951 s32 s32Error = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001952
1953 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +09001954 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001955
Glen Leefbf53792015-12-21 14:18:40 +09001956 s32Error = wilc_add_beacon(vif, 0, 0, beacon->head_len,
1957 (u8 *)beacon->head, beacon->tail_len,
1958 (u8 *)beacon->tail);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001959
1960 return s32Error;
1961}
1962
Chaehyun Limc8cddd72015-09-14 12:24:14 +09001963static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001964{
Leo Kime6e12662015-09-16 18:36:03 +09001965 s32 s32Error = 0;
Chaehyun Lim27268872015-09-15 14:06:13 +09001966 struct wilc_priv *priv;
Glen Leecf601062015-12-21 14:18:39 +09001967 struct wilc_vif *vif;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +09001968 u8 NullBssid[ETH_ALEN] = {0};
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001969
Leo Kim7ae43362015-09-16 18:35:59 +09001970 if (!wiphy)
1971 return -EFAULT;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001972
1973 priv = wiphy_priv(wiphy);
Glen Leecf601062015-12-21 14:18:39 +09001974 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001975
Glen Leeba615f12016-01-25 16:35:15 +09001976 wilc_wlan_set_bssid(dev, NullBssid, AP_MODE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001977
Glen Leefbf53792015-12-21 14:18:40 +09001978 s32Error = wilc_del_beacon(vif);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001979
Leo Kim7dc1d0c2015-09-16 18:36:00 +09001980 if (s32Error)
Leo Kim06fb9332016-02-04 18:15:55 +09001981 netdev_err(dev, "Host delete beacon fail\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001982
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001983 return s32Error;
1984}
1985
Chaehyun Limed269552015-09-14 12:24:15 +09001986static int add_station(struct wiphy *wiphy, struct net_device *dev,
1987 const u8 *mac, struct station_parameters *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001988{
Leo Kime6e12662015-09-16 18:36:03 +09001989 s32 s32Error = 0;
Chaehyun Lim27268872015-09-15 14:06:13 +09001990 struct wilc_priv *priv;
Tony Cho6a89ba92015-09-21 12:16:46 +09001991 struct add_sta_param strStaParams = { {0} };
Glen Leea4cac482015-12-21 14:18:36 +09001992 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001993
Leo Kim7ae43362015-09-16 18:35:59 +09001994 if (!wiphy)
1995 return -EFAULT;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001996
1997 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +09001998 vif = netdev_priv(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001999
Glen Leea4cac482015-12-21 14:18:36 +09002000 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
Leo Kim2353c382015-10-29 12:05:41 +09002001 memcpy(strStaParams.bssid, mac, ETH_ALEN);
Chaehyun Limd00d2ba2015-08-10 11:33:19 +09002002 memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
Leo Kim4101eb82015-10-29 12:05:42 +09002003 strStaParams.aid = params->aid;
Leo Kime7342232015-10-29 12:05:43 +09002004 strStaParams.rates_len = params->supported_rates_len;
Leo Kima622e012015-10-29 12:05:44 +09002005 strStaParams.rates = params->supported_rates;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002006
Leo Kim369a1d32015-12-21 14:18:23 +09002007 if (!params->ht_capa) {
Leo Kim22520122015-10-29 12:05:45 +09002008 strStaParams.ht_supported = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002009 } else {
Leo Kim22520122015-10-29 12:05:45 +09002010 strStaParams.ht_supported = true;
Leo Kim0d073f62015-10-29 12:05:46 +09002011 strStaParams.ht_capa_info = params->ht_capa->cap_info;
Leo Kimfba1f2d2015-10-29 12:05:47 +09002012 strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
Leo Kim5ebbf4f2015-10-29 12:05:48 +09002013 memcpy(strStaParams.ht_supp_mcs_set,
2014 &params->ht_capa->mcs,
2015 WILC_SUPP_MCS_SET_SIZE);
Leo Kim223741d2015-10-29 12:05:49 +09002016 strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
Leo Kim74fe73c2015-10-29 12:05:50 +09002017 strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
Leo Kima486baf2015-10-29 12:05:51 +09002018 strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002019 }
2020
Leo Kimf676e172015-10-29 12:05:52 +09002021 strStaParams.flags_mask = params->sta_flags_mask;
Leo Kim67ab64e2015-10-29 12:05:53 +09002022 strStaParams.flags_set = params->sta_flags_set;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002023
Glen Leefbf53792015-12-21 14:18:40 +09002024 s32Error = wilc_add_station(vif, &strStaParams);
Leo Kim7dc1d0c2015-09-16 18:36:00 +09002025 if (s32Error)
Leo Kim06fb9332016-02-04 18:15:55 +09002026 netdev_err(dev, "Host add station fail\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002027 }
2028
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002029 return s32Error;
2030}
2031
Chaehyun Lima0a8be92015-09-14 12:24:16 +09002032static int del_station(struct wiphy *wiphy, struct net_device *dev,
2033 struct station_del_parameters *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002034{
Arnd Bergmann057d1e92015-06-01 21:06:44 +02002035 const u8 *mac = params->mac;
Leo Kime6e12662015-09-16 18:36:03 +09002036 s32 s32Error = 0;
Chaehyun Lim27268872015-09-15 14:06:13 +09002037 struct wilc_priv *priv;
Glen Leea4cac482015-12-21 14:18:36 +09002038 struct wilc_vif *vif;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09002039
Leo Kim7ae43362015-09-16 18:35:59 +09002040 if (!wiphy)
2041 return -EFAULT;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002042
2043 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +09002044 vif = netdev_priv(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002045
Glen Leea4cac482015-12-21 14:18:36 +09002046 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
Chris Parka1b56a42016-02-22 13:11:54 +09002047 if (!mac)
Glen Leefbf53792015-12-21 14:18:40 +09002048 s32Error = wilc_del_allstation(vif,
2049 priv->assoc_stainfo.au8Sta_AssociatedBss);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002050
Glen Leefbf53792015-12-21 14:18:40 +09002051 s32Error = wilc_del_station(vif, mac);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002052
Leo Kim7dc1d0c2015-09-16 18:36:00 +09002053 if (s32Error)
Leo Kim06fb9332016-02-04 18:15:55 +09002054 netdev_err(dev, "Host delete station fail\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002055 }
2056 return s32Error;
2057}
2058
Chaehyun Lim14b42082015-09-14 12:24:17 +09002059static int change_station(struct wiphy *wiphy, struct net_device *dev,
2060 const u8 *mac, struct station_parameters *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002061{
Leo Kime6e12662015-09-16 18:36:03 +09002062 s32 s32Error = 0;
Chaehyun Lim27268872015-09-15 14:06:13 +09002063 struct wilc_priv *priv;
Tony Cho6a89ba92015-09-21 12:16:46 +09002064 struct add_sta_param strStaParams = { {0} };
Glen Leea4cac482015-12-21 14:18:36 +09002065 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002066
Leo Kim7ae43362015-09-16 18:35:59 +09002067 if (!wiphy)
2068 return -EFAULT;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002069
2070 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +09002071 vif = netdev_priv(dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002072
Glen Leea4cac482015-12-21 14:18:36 +09002073 if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) {
Leo Kim2353c382015-10-29 12:05:41 +09002074 memcpy(strStaParams.bssid, mac, ETH_ALEN);
Leo Kim4101eb82015-10-29 12:05:42 +09002075 strStaParams.aid = params->aid;
Leo Kime7342232015-10-29 12:05:43 +09002076 strStaParams.rates_len = params->supported_rates_len;
Leo Kima622e012015-10-29 12:05:44 +09002077 strStaParams.rates = params->supported_rates;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002078
Leo Kim369a1d32015-12-21 14:18:23 +09002079 if (!params->ht_capa) {
Leo Kim22520122015-10-29 12:05:45 +09002080 strStaParams.ht_supported = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002081 } else {
Leo Kim22520122015-10-29 12:05:45 +09002082 strStaParams.ht_supported = true;
Leo Kim0d073f62015-10-29 12:05:46 +09002083 strStaParams.ht_capa_info = params->ht_capa->cap_info;
Leo Kimfba1f2d2015-10-29 12:05:47 +09002084 strStaParams.ht_ampdu_params = params->ht_capa->ampdu_params_info;
Leo Kim5ebbf4f2015-10-29 12:05:48 +09002085 memcpy(strStaParams.ht_supp_mcs_set,
2086 &params->ht_capa->mcs,
2087 WILC_SUPP_MCS_SET_SIZE);
Leo Kim223741d2015-10-29 12:05:49 +09002088 strStaParams.ht_ext_params = params->ht_capa->extended_ht_cap_info;
Leo Kim74fe73c2015-10-29 12:05:50 +09002089 strStaParams.ht_tx_bf_cap = params->ht_capa->tx_BF_cap_info;
Leo Kima486baf2015-10-29 12:05:51 +09002090 strStaParams.ht_ante_sel = params->ht_capa->antenna_selection_info;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002091 }
2092
Leo Kimf676e172015-10-29 12:05:52 +09002093 strStaParams.flags_mask = params->sta_flags_mask;
Leo Kim67ab64e2015-10-29 12:05:53 +09002094 strStaParams.flags_set = params->sta_flags_set;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002095
Glen Leefbf53792015-12-21 14:18:40 +09002096 s32Error = wilc_edit_station(vif, &strStaParams);
Leo Kim7dc1d0c2015-09-16 18:36:00 +09002097 if (s32Error)
Leo Kim06fb9332016-02-04 18:15:55 +09002098 netdev_err(dev, "Host edit station fail\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002099 }
2100 return s32Error;
2101}
2102
Chaehyun Lim37316e82015-09-22 18:34:52 +09002103static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
2104 const char *name,
2105 unsigned char name_assign_type,
2106 enum nl80211_iftype type,
2107 u32 *flags,
2108 struct vif_params *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002109{
Glen Leea4cac482015-12-21 14:18:36 +09002110 struct wilc_vif *vif;
Chaehyun Lim27268872015-09-15 14:06:13 +09002111 struct wilc_priv *priv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002112 struct net_device *new_ifc = NULL;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09002113
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002114 priv = wiphy_priv(wiphy);
Glen Leea4cac482015-12-21 14:18:36 +09002115 vif = netdev_priv(priv->wdev->netdev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002116
2117
2118 if (type == NL80211_IFTYPE_MONITOR) {
Glen Lee1006b5c2015-12-21 14:18:38 +09002119 new_ifc = WILC_WFI_init_mon_interface(name, vif->ndev);
Leo Kim369a1d32015-12-21 14:18:23 +09002120 if (new_ifc) {
Glen Leea4cac482015-12-21 14:18:36 +09002121 vif = netdev_priv(priv->wdev->netdev);
2122 vif->monitor_flag = 1;
Leo Kim06fb9332016-02-04 18:15:55 +09002123 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002124 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002125 return priv->wdev;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002126}
2127
Chaehyun Lim956d7212015-09-22 18:34:49 +09002128static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002129{
Leo Kime6e12662015-09-16 18:36:03 +09002130 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002131}
2132
Glen Lee73584a42016-01-25 16:35:10 +09002133static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
2134{
2135 struct wilc_priv *priv = wiphy_priv(wiphy);
2136 struct wilc_vif *vif = netdev_priv(priv->dev);
2137
2138 if (!wow && wilc_wlan_get_num_conn_ifcs(vif->wilc))
2139 vif->wilc->suspend_event = true;
2140 else
2141 vif->wilc->suspend_event = false;
2142
2143 return 0;
2144}
2145
2146static int wilc_resume(struct wiphy *wiphy)
2147{
2148 struct wilc_priv *priv = wiphy_priv(wiphy);
2149 struct wilc_vif *vif = netdev_priv(priv->dev);
2150
2151 netdev_info(vif->ndev, "cfg resume\n");
2152 return 0;
2153}
2154
2155static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)
2156{
2157 struct wilc_priv *priv = wiphy_priv(wiphy);
2158 struct wilc_vif *vif = netdev_priv(priv->dev);
2159
2160 netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled);
2161}
2162
Glen Lee70418792016-02-04 18:15:27 +09002163static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
2164 enum nl80211_tx_power_setting type, int mbm)
2165{
2166 int ret;
2167 s32 tx_power = MBM_TO_DBM(mbm);
2168 struct wilc_priv *priv = wiphy_priv(wiphy);
2169 struct wilc_vif *vif = netdev_priv(priv->dev);
2170
2171 if (tx_power < 0)
2172 tx_power = 0;
2173 else if (tx_power > 18)
2174 tx_power = 18;
2175 ret = wilc_set_tx_power(vif, tx_power);
2176 if (ret)
2177 netdev_err(vif->ndev, "Failed to set tx power\n");
2178
2179 return ret;
2180}
2181
2182static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
2183 int *dbm)
2184{
2185 int ret;
2186 struct wilc_priv *priv = wiphy_priv(wiphy);
2187 struct wilc_vif *vif = netdev_priv(priv->dev);
Leo Kim8827bd82016-03-18 21:23:16 +09002188 struct wilc *wl;
2189
2190 wl = vif->wilc;
2191
2192 /* If firmware is not started, return. */
2193 if (!wl->initialized)
2194 return -EIO;
Glen Lee70418792016-02-04 18:15:27 +09002195
2196 ret = wilc_get_tx_power(vif, (u8 *)dbm);
2197 if (ret)
2198 netdev_err(vif->ndev, "Failed to get tx power\n");
2199
2200 return ret;
2201}
2202
Chaehyun Lim08241922015-09-15 14:06:12 +09002203static struct cfg80211_ops wilc_cfg80211_ops = {
Chaehyun Lim80785a92015-09-14 12:24:01 +09002204 .set_monitor_channel = set_channel,
Chaehyun Lim0e30d062015-09-14 12:24:02 +09002205 .scan = scan,
Chaehyun Lim4ffbcdb2015-09-14 12:24:03 +09002206 .connect = connect,
Chaehyun Limb027cde2015-09-14 12:24:04 +09002207 .disconnect = disconnect,
Chaehyun Lim953d4172015-09-14 12:24:05 +09002208 .add_key = add_key,
Chaehyun Lim3044ba72015-09-14 12:24:06 +09002209 .del_key = del_key,
Chaehyun Limf4893df2015-09-14 12:24:07 +09002210 .get_key = get_key,
Chaehyun Lim0f5b8ca2015-09-14 12:24:08 +09002211 .set_default_key = set_default_key,
Chaehyun Lim69deb4c2015-09-14 12:24:09 +09002212 .add_virtual_intf = add_virtual_intf,
Chaehyun Limb4a73352015-09-14 12:24:10 +09002213 .del_virtual_intf = del_virtual_intf,
Chaehyun Lim3615e9a2015-09-14 12:24:11 +09002214 .change_virtual_intf = change_virtual_intf,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002215
Chaehyun Lima13168d2015-09-14 12:24:12 +09002216 .start_ap = start_ap,
Chaehyun Lim2a4c84d2015-09-14 12:24:13 +09002217 .change_beacon = change_beacon,
Chaehyun Limc8cddd72015-09-14 12:24:14 +09002218 .stop_ap = stop_ap,
Chaehyun Limed269552015-09-14 12:24:15 +09002219 .add_station = add_station,
Chaehyun Lima0a8be92015-09-14 12:24:16 +09002220 .del_station = del_station,
Chaehyun Lim14b42082015-09-14 12:24:17 +09002221 .change_station = change_station,
Chaehyun Limf06f5622015-09-14 12:24:18 +09002222 .get_station = get_station,
Chaehyun Limbdb63382015-09-14 12:24:19 +09002223 .dump_station = dump_station,
Chaehyun Lima5f7db62015-09-14 12:24:20 +09002224 .change_bss = change_bss,
Chaehyun Lima76b63e2015-09-14 12:24:21 +09002225 .set_wiphy_params = set_wiphy_params,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002226
Chaehyun Lim4d466572015-09-14 12:24:22 +09002227 .set_pmksa = set_pmksa,
Chaehyun Lim1ff86d92015-09-14 12:24:23 +09002228 .del_pmksa = del_pmksa,
Chaehyun Limb33c39b2015-09-14 12:24:24 +09002229 .flush_pmksa = flush_pmksa,
Chaehyun Lim6d19d692015-09-14 12:24:25 +09002230 .remain_on_channel = remain_on_channel,
Chaehyun Lim1dd54402015-09-14 12:24:26 +09002231 .cancel_remain_on_channel = cancel_remain_on_channel,
Chaehyun Lim4a2f9b32015-09-14 12:24:27 +09002232 .mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,
Chaehyun Lim12a26a32015-09-14 12:24:28 +09002233 .mgmt_tx = mgmt_tx,
Chaehyun Lim8e0735c2015-09-20 15:51:16 +09002234 .mgmt_frame_register = wilc_mgmt_frame_register,
Chaehyun Lim46530672015-09-22 18:34:46 +09002235 .set_power_mgmt = set_power_mgmt,
Chaehyun Lima8047e22015-09-22 18:34:48 +09002236 .set_cqm_rssi_config = set_cqm_rssi_config,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002237
Glen Lee73584a42016-01-25 16:35:10 +09002238 .suspend = wilc_suspend,
2239 .resume = wilc_resume,
2240 .set_wakeup = wilc_set_wakeup,
Glen Lee70418792016-02-04 18:15:27 +09002241 .set_tx_power = set_tx_power,
2242 .get_tx_power = get_tx_power,
Glen Lee73584a42016-01-25 16:35:10 +09002243
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002244};
2245
Arnd Bergmann1608c402015-11-16 15:04:53 +01002246static struct wireless_dev *WILC_WFI_CfgAlloc(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002247{
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002248 struct wireless_dev *wdev;
2249
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002250 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
Leo Kim06fb9332016-02-04 18:15:55 +09002251 if (!wdev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002252 goto _fail_;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002253
Chaehyun Lim27268872015-09-15 14:06:13 +09002254 wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
Leo Kim06fb9332016-02-04 18:15:55 +09002255 if (!wdev->wiphy)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002256 goto _fail_mem_;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002257
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002258 WILC_WFI_band_2ghz.ht_cap.ht_supported = 1;
2259 WILC_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
2260 WILC_WFI_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
2261 WILC_WFI_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
2262 WILC_WFI_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002263
Johannes Berg57fbcce2016-04-12 15:56:15 +02002264 wdev->wiphy->bands[NL80211_BAND_2GHZ] = &WILC_WFI_band_2ghz;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002265
2266 return wdev;
2267
2268_fail_mem_:
2269 kfree(wdev);
2270_fail_:
2271 return NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002272}
Leo Kima89f7c52015-11-25 11:59:41 +09002273
Arnd Bergmann2e7d5372015-11-16 15:05:03 +01002274struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *dev)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002275{
Chaehyun Lim27268872015-09-15 14:06:13 +09002276 struct wilc_priv *priv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002277 struct wireless_dev *wdev;
Leo Kime6e12662015-09-16 18:36:03 +09002278 s32 s32Error = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002279
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002280 wdev = WILC_WFI_CfgAlloc();
Leo Kim369a1d32015-12-21 14:18:23 +09002281 if (!wdev) {
Leo Kim06fb9332016-02-04 18:15:55 +09002282 netdev_err(net, "wiphy new allocate failed\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002283 return NULL;
2284 }
2285
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002286 priv = wdev_priv(wdev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002287 priv->wdev = wdev;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002288 wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID;
Sudip Mukherjeeabb4f8a2016-02-05 15:26:54 +05302289#ifdef CONFIG_PM
Glen Lee73584a42016-01-25 16:35:10 +09002290 wdev->wiphy->wowlan = &wowlan_support;
Sudip Mukherjeeabb4f8a2016-02-05 15:26:54 +05302291#endif
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002292 wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002293 wdev->wiphy->max_scan_ie_len = 1000;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002294 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002295 wdev->wiphy->cipher_suites = cipher_suites;
2296 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002297 wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002298
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002299 wdev->wiphy->max_remain_on_channel_duration = 500;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002300 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) | BIT(NL80211_IFTYPE_P2P_GO) |
2301 BIT(NL80211_IFTYPE_P2P_CLIENT);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002302 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002303 wdev->iftype = NL80211_IFTYPE_STATION;
2304
Arnd Bergmann2e7d5372015-11-16 15:05:03 +01002305 set_wiphy_dev(wdev->wiphy, dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002306
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002307 s32Error = wiphy_register(wdev->wiphy);
Leo Kim06fb9332016-02-04 18:15:55 +09002308 if (s32Error)
2309 netdev_err(net, "Cannot register wiphy device\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002310
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002311 priv->dev = net;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002312 return wdev;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002313}
Leo Kima89f7c52015-11-25 11:59:41 +09002314
Chaehyun Limdd4b6a82015-09-20 15:51:25 +09002315int wilc_init_host_int(struct net_device *net)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002316{
Chaehyun Lim1a8ccd82015-09-20 15:51:23 +09002317 int s32Error = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002318
Chaehyun Lim27268872015-09-15 14:06:13 +09002319 struct wilc_priv *priv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002320
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002321 priv = wdev_priv(net->ieee80211_ptr);
2322 if (op_ifcs == 0) {
Greg Kroah-Hartman93dee8e2015-08-14 20:28:32 -07002323 setup_timer(&hAgingTimer, remove_network_from_shadow, 0);
Arnd Bergmann0e1af732015-11-16 15:04:54 +01002324 setup_timer(&wilc_during_ip_timer, clear_duringIP, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002325 }
2326 op_ifcs++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002327
Dean Lee72ed4dc2015-06-12 14:11:44 +09002328 priv->gbAutoRateAdjusted = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002329
Dean Lee72ed4dc2015-06-12 14:11:44 +09002330 priv->bInP2PlistenState = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002331
Chaehyun Lim08662092016-03-28 13:56:00 +09002332 mutex_init(&priv->scan_req_lock);
Leo Kim48b28df2016-02-04 18:15:32 +09002333 s32Error = wilc_init(net, &priv->hif_drv);
Chaehyun Limf1fe9c42015-09-20 15:51:22 +09002334 if (s32Error)
Leo Kim06fb9332016-02-04 18:15:55 +09002335 netdev_err(net, "Error while initializing hostinterface\n");
Chaehyun Limf1fe9c42015-09-20 15:51:22 +09002336
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002337 return s32Error;
2338}
2339
Chaehyun Lima9a16822015-09-20 15:51:24 +09002340int wilc_deinit_host_int(struct net_device *net)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002341{
Chaehyun Lim1a8ccd82015-09-20 15:51:23 +09002342 int s32Error = 0;
Glen Leecf601062015-12-21 14:18:39 +09002343 struct wilc_vif *vif;
Chaehyun Lim27268872015-09-15 14:06:13 +09002344 struct wilc_priv *priv;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09002345
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002346 priv = wdev_priv(net->ieee80211_ptr);
Glen Leecf601062015-12-21 14:18:39 +09002347 vif = netdev_priv(priv->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002348
Dean Lee72ed4dc2015-06-12 14:11:44 +09002349 priv->gbAutoRateAdjusted = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002350
Dean Lee72ed4dc2015-06-12 14:11:44 +09002351 priv->bInP2PlistenState = false;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002352
2353 op_ifcs--;
2354
Glen Leefbf53792015-12-21 14:18:40 +09002355 s32Error = wilc_deinit(vif);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002356
Leo Kimd14991a2015-11-19 15:56:22 +09002357 clear_shadow_scan();
Chris Park368949a2016-02-04 18:24:03 +09002358 if (op_ifcs == 0)
Arnd Bergmann0e1af732015-11-16 15:04:54 +01002359 del_timer_sync(&wilc_during_ip_timer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002360
Chaehyun Limf1fe9c42015-09-20 15:51:22 +09002361 if (s32Error)
Leo Kim06fb9332016-02-04 18:15:55 +09002362 netdev_err(net, "Error while deintializing host interface\n");
Chaehyun Limf1fe9c42015-09-20 15:51:22 +09002363
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002364 return s32Error;
2365}
2366
Chaehyun Lim96da20a2015-09-20 15:51:08 +09002367void wilc_free_wiphy(struct net_device *net)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002368{
Chris Parkd9766d52016-02-22 13:12:04 +09002369 if (!net)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002370 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002371
Chris Parkd9766d52016-02-22 13:12:04 +09002372 if (!net->ieee80211_ptr)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002373 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002374
Chris Parkd9766d52016-02-22 13:12:04 +09002375 if (!net->ieee80211_ptr->wiphy)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002376 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002377
2378 wiphy_unregister(net->ieee80211_ptr->wiphy);
2379
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002380 wiphy_free(net->ieee80211_ptr->wiphy);
2381 kfree(net->ieee80211_ptr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09002382}