[9610] wlbt: SCSC Driver version 10.9.1.0
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / drivers / net / wireless / scsc / mlme.c
1 /*****************************************************************************
2 *
3 * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
4 *
5 ****************************************************************************/
6
7 #include <linux/delay.h>
8 #include <net/cfg80211.h>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <scsc/scsc_log_collector.h>
12
13 #include "dev.h"
14 #include "debug.h"
15 #include "mlme.h"
16 #include "mib.h"
17 #include "mgt.h"
18 #include "cac.h"
19
20 #define SLSI_SCAN_PRIVATE_IE_CHANNEL_LIST_HEADER_LEN 7
21 #define SLSI_SCAN_PRIVATE_IE_SSID_FILTER_HEADER_LEN 7
22 #define SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE 3
23 #define SLSI_CHANN_INFO_HT_SCB 0x0100
24
25 #define SLSI_NOA_CONFIG_REQUEST_ID (1)
26 #define SLSI_MLME_ARP_DROP_FREE_SLOTS_COUNT 16
27
28 static bool missing_cfm_ind_panic = true;
29 module_param(missing_cfm_ind_panic, bool, S_IRUGO | S_IWUSR);
30 MODULE_PARM_DESC(missing_cfm_ind_panic, "Panic on missing confirm or indication from the chip");
31
32 struct slsi_mlme_rsse {
33 u8 group_cs_count;
34 const u8 *group_cs;
35 u8 pairwise_cs_count;
36 const u8 *pairwise_cs;
37 u8 akm_suite_count;
38 const u8 *akm_suite;
39 u8 pmkid_count;
40 const u8 *pmkid;
41 const u8 *group_mgmt_cs; /* used for PMF*/
42 };
43
44 static struct sk_buff *slsi_mlme_wait_for_cfm(struct slsi_dev *sdev, struct slsi_sig_send *sig_wait)
45 {
46 struct sk_buff *cfm = NULL;
47 int tm;
48
49 tm = wait_for_completion_timeout(&sig_wait->completion, msecs_to_jiffies(*sdev->sig_wait_cfm_timeout));
50 spin_lock_bh(&sig_wait->send_signal_lock);
51
52 /* Confirm timed out? */
53 if (!sig_wait->cfm) {
54 SLSI_ERR(sdev, "No cfm(0x%.4X) for req(0x%04X) senderid=0x%x\n", sig_wait->cfm_id, sig_wait->req_id, sig_wait->process_id);
55 if (tm == 0) {
56 char reason[80];
57
58 WARN(1, "Timeout - confirm 0x%04x not received from chip\n", sig_wait->cfm_id);
59 if (missing_cfm_ind_panic) {
60 snprintf(reason, sizeof(reason), "Timed out while waiting for the cfm(0x%.4x) for req(0x%04x)",
61 sig_wait->cfm_id, sig_wait->req_id);
62
63 spin_unlock_bh(&sig_wait->send_signal_lock);
64 slsi_sm_service_failed(sdev, reason);
65 spin_lock_bh(&sig_wait->send_signal_lock);
66 }
67 } else {
68 WARN(1, "Confirm 0x%04x lost\n", sig_wait->cfm_id);
69 }
70 } else {
71 WARN_ON(fapi_get_u16(sig_wait->cfm, receiver_pid) != sig_wait->process_id);
72 WARN_ON(fapi_get_u16(sig_wait->cfm, id) != sig_wait->cfm_id);
73 }
74
75 sig_wait->cfm_id = 0;
76 cfm = sig_wait->cfm;
77 sig_wait->cfm = NULL;
78 if (!cfm)
79 sig_wait->ind_id = 0;
80
81 spin_unlock_bh(&sig_wait->send_signal_lock);
82
83 return cfm;
84 }
85
86 static int panic_on_lost_ind(u16 ind_id)
87 {
88 if (ind_id == MLME_SCAN_DONE_IND)
89 return 0;
90 return 1;
91 }
92
93 static struct sk_buff *slsi_mlme_wait_for_ind(struct slsi_dev *sdev, struct net_device *dev, struct slsi_sig_send *sig_wait, u16 ind_id)
94 {
95 struct netdev_vif *ndev_vif = netdev_priv(dev);
96 struct sk_buff *ind = NULL;
97 int tm = 0;
98
99 /* The indication and confirm may have been received in the same HIP read.
100 * The HIP receive buffer processes all received signals in one thread whilst the
101 * waiting process may not be scheduled even if the "complete" call is made.
102 * In this scenario, the complete() call has already been made for this object
103 * and the wait will return immediately.
104 */
105 if (ind_id == MLME_SCAN_DONE_IND)
106 /* To handle the coex scenario where BTscan has high priority increasing the wait time to 40 secs */
107 tm = wait_for_completion_timeout(&sig_wait->completion, msecs_to_jiffies(SLSI_SCAN_DONE_IND_WAIT_TIMEOUT));
108 else if ((ind_id == MLME_DISCONNECT_IND) && (ndev_vif->vif_type == FAPI_VIFTYPE_AP))
109 tm = wait_for_completion_timeout(&sig_wait->completion, msecs_to_jiffies(sdev->device_config.ap_disconnect_ind_timeout));
110 else
111 tm = wait_for_completion_timeout(&sig_wait->completion, msecs_to_jiffies(*sdev->sig_wait_cfm_timeout));
112
113 spin_lock_bh(&sig_wait->send_signal_lock);
114
115 /* Indication timed out? */
116 if (!sig_wait->ind) {
117 SLSI_ERR(sdev, "No ind(0x%.4X) for req(0x%04X) senderid=0x%x\n", sig_wait->ind_id, sig_wait->req_id, sig_wait->process_id);
118 if (tm == 0) {
119 char reason[80];
120
121 WARN(1, "Timeout - indication 0x%04x not received from chip\n", sig_wait->ind_id);
122 if (missing_cfm_ind_panic && panic_on_lost_ind(ind_id)) {
123 snprintf(reason, sizeof(reason), "Timed out while waiting for the ind(0x%.4x) for req(0x%04x)",
124 sig_wait->ind_id, sig_wait->req_id);
125
126 spin_unlock_bh(&sig_wait->send_signal_lock);
127 slsi_sm_service_failed(sdev, reason);
128 spin_lock_bh(&sig_wait->send_signal_lock);
129 }
130 } else {
131 WARN(1, "Indication 0x%04x lost\n", sig_wait->ind_id);
132 }
133 } else {
134 WARN_ON(fapi_get_u16(sig_wait->ind, receiver_pid) != sig_wait->process_id);
135 WARN_ON(fapi_get_u16(sig_wait->ind, id) != sig_wait->ind_id);
136 }
137
138 sig_wait->ind_id = 0;
139 ind = sig_wait->ind;
140 sig_wait->ind = NULL;
141
142 spin_unlock_bh(&sig_wait->send_signal_lock);
143
144 return ind;
145 }
146
147 /* mib_error: NULL when not required
148 * ind: 0 when not required, if used validate_cfm_wait_ind MUST be supplied
149 * validate_cfm_wait_ind: NULL when not required, if used ind MUS not be 0
150 * NOTE: dev can be NULL!
151 */
152 static struct sk_buff *slsi_mlme_tx_rx(struct slsi_dev *sdev,
153 struct net_device *dev,
154 struct sk_buff *skb,
155 u16 cfm_id,
156 struct sk_buff **mib_error,
157 u16 ind_id,
158 bool (*validate_cfm_wait_ind)(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm))
159 {
160 struct sk_buff *rx = NULL;
161 int err;
162 u16 req_id = fapi_get_u16(skb, id);
163 struct slsi_sig_send *sig_wait = &sdev->sig_wait;
164
165 if (dev) {
166 struct netdev_vif *ndev_vif = netdev_priv(dev);
167
168 sig_wait = &ndev_vif->sig_wait;
169 }
170 if (sdev->mlme_blocked) {
171 SLSI_DBG3(sdev, SLSI_TX, "Rejected. mlme_blocked=%d\n", sdev->mlme_blocked);
172 slsi_kfree_skb(skb);
173 return NULL;
174 }
175
176 slsi_wakelock(&sdev->wlan_wl);
177 SLSI_MUTEX_LOCK(sig_wait->mutex);
178
179 spin_lock_bh(&sig_wait->send_signal_lock);
180 if (++sig_wait->process_id > SLSI_TX_PROCESS_ID_MAX)
181 sig_wait->process_id = SLSI_TX_PROCESS_ID_MIN;
182
183 WARN_ON(sig_wait->cfm);
184 WARN_ON(sig_wait->ind);
185 slsi_kfree_skb(sig_wait->cfm);
186 slsi_kfree_skb(sig_wait->ind);
187 slsi_kfree_skb(sig_wait->mib_error);
188 sig_wait->cfm = NULL;
189 sig_wait->ind = NULL;
190 sig_wait->mib_error = NULL;
191 sig_wait->req_id = req_id;
192 sig_wait->cfm_id = cfm_id;
193 sig_wait->ind_id = ind_id;
194
195 fapi_set_u16(skb, sender_pid, sig_wait->process_id);
196 spin_unlock_bh(&sig_wait->send_signal_lock);
197
198 err = slsi_tx_control(sdev, dev, skb);
199 if (err != 0) {
200 SLSI_ERR(sdev, "Failed to send mlme signal:0x%.4X, err=%d\n", req_id, err);
201 slsi_kfree_skb(skb);
202 goto clean_exit;
203 }
204
205 if (cfm_id) {
206 rx = slsi_mlme_wait_for_cfm(sdev, sig_wait);
207 if (rx && ind_id) {
208 /* The cfm skb is owned by the validate_cfm_wait_ind() function and MUST be freed or saved there */
209 if (validate_cfm_wait_ind(sdev, dev, rx)) {
210 rx = slsi_mlme_wait_for_ind(sdev, dev, sig_wait, ind_id);
211 } else {
212 sig_wait->ind_id = 0; /* Reset as there is no wait for indication */
213 rx = NULL;
214 }
215 }
216 } else if (ind_id) {
217 rx = slsi_mlme_wait_for_ind(sdev, dev, sig_wait, ind_id);
218 }
219
220 /* The cfm_id and ind_id should ALWAYS be 0 at this point */
221 WARN_ON(sig_wait->cfm_id);
222 WARN_ON(sig_wait->ind_id);
223 WARN_ON(sig_wait->cfm);
224 WARN_ON(sig_wait->ind);
225 clean_exit:
226
227 spin_lock_bh(&sig_wait->send_signal_lock);
228
229 sig_wait->req_id = 0;
230 sig_wait->cfm_id = 0;
231 sig_wait->ind_id = 0;
232 slsi_kfree_skb(sig_wait->cfm);
233 slsi_kfree_skb(sig_wait->ind);
234 sig_wait->cfm = NULL;
235 sig_wait->ind = NULL;
236
237 if (mib_error)
238 *mib_error = sig_wait->mib_error;
239 else
240 slsi_kfree_skb(sig_wait->mib_error);
241 sig_wait->mib_error = NULL;
242 spin_unlock_bh(&sig_wait->send_signal_lock);
243
244 SLSI_MUTEX_UNLOCK(sig_wait->mutex);
245
246 slsi_wakeunlock(&sdev->wlan_wl);
247 return rx;
248 }
249
250 /**
251 * NOTE: dev can be NULL!
252 */
253 int slsi_mlme_req(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
254 {
255 int ret = 0;
256 struct slsi_sig_send *sig_wait = &sdev->sig_wait;
257
258 if (dev) {
259 struct netdev_vif *ndev_vif = netdev_priv(dev);
260
261 sig_wait = &ndev_vif->sig_wait;
262 }
263 spin_lock_bh(&sig_wait->send_signal_lock);
264 if (++sig_wait->process_id > SLSI_TX_PROCESS_ID_MAX)
265 sig_wait->process_id = SLSI_TX_PROCESS_ID_MIN;
266 fapi_set_u16(skb, sender_pid, sig_wait->process_id);
267 spin_unlock_bh(&sig_wait->send_signal_lock);
268
269 ret = slsi_tx_control(sdev, dev, skb);
270 if (ret)
271 slsi_kfree_skb(skb);
272 return ret;
273 }
274
275 struct sk_buff *slsi_mlme_req_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 ind_id)
276 {
277 if (WARN_ON(!ind_id))
278 goto err;
279 return slsi_mlme_tx_rx(sdev, dev, skb, 0, NULL, ind_id, NULL);
280 err:
281 slsi_kfree_skb(skb);
282 return NULL;
283 }
284
285 struct sk_buff *slsi_mlme_req_no_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
286 {
287 return slsi_mlme_tx_rx(sdev, dev, skb, 0, NULL, 0, NULL);
288 }
289
290 struct sk_buff *slsi_mlme_req_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 cfm_id)
291 {
292 if (WARN_ON(!cfm_id))
293 goto err;
294 return slsi_mlme_tx_rx(sdev, dev, skb, cfm_id, NULL, 0, NULL);
295 err:
296 slsi_kfree_skb(skb);
297 return NULL;
298 }
299
300 /* NOTE: dev can be NULL! */
301 static inline struct sk_buff *slsi_mlme_req_cfm_mib(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 cfm_id, struct sk_buff **mib_error)
302 {
303 if (WARN_ON(!cfm_id))
304 goto err;
305 if (WARN_ON(!mib_error))
306 goto err;
307 return slsi_mlme_tx_rx(sdev, dev, skb, cfm_id, mib_error, 0, NULL);
308 err:
309 slsi_kfree_skb(skb);
310 return NULL;
311 }
312
313 /* NOTE: dev can be NULL! */
314 static inline struct sk_buff *slsi_mlme_req_cfm_ind(struct slsi_dev *sdev,
315 struct net_device *dev,
316 struct sk_buff *skb,
317 u16 cfm_id,
318 u16 ind_id,
319 bool (*validate_cfm_wait_ind)(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm))
320 {
321 if (WARN_ON(!cfm_id))
322 goto err;
323 if (WARN_ON(!ind_id))
324 goto err;
325 if (WARN_ON(!validate_cfm_wait_ind))
326 goto err;
327
328 return slsi_mlme_tx_rx(sdev, dev, skb, cfm_id, NULL, ind_id, validate_cfm_wait_ind);
329
330 err:
331 slsi_kfree_skb(skb);
332 return NULL;
333 }
334
335 static struct ieee80211_reg_rule *slsi_get_reg_rule(u32 center_freq, struct slsi_802_11d_reg_domain *domain_info)
336 {
337 struct ieee80211_reg_rule *rule;
338 int i;
339
340 for (i = 0; i < domain_info->regdomain->n_reg_rules; i++) {
341 rule = &domain_info->regdomain->reg_rules[i];
342
343 /* Consider 10Mhz on both side from the center frequency */
344 if (((center_freq - MHZ_TO_KHZ(10)) >= rule->freq_range.start_freq_khz) &&
345 ((center_freq + MHZ_TO_KHZ(10)) <= rule->freq_range.end_freq_khz))
346 return rule;
347 }
348
349 return NULL;
350 }
351
352 u16 slsi_compute_chann_info(struct slsi_dev *sdev, u16 width, u16 center_freq0, u16 channel_freq)
353 {
354 u16 chann_info;
355 u16 prim_chan_pos = 0;
356
357 SLSI_DBG3(sdev, SLSI_MLME, "compute channel info\n");
358 switch (width) {
359 case NL80211_CHAN_WIDTH_20:
360 chann_info = 20;
361 break;
362 case NL80211_CHAN_WIDTH_40:
363 chann_info = 40;
364 /* Check HT Minus */
365 if (center_freq0 < channel_freq)
366 chann_info |= SLSI_CHANN_INFO_HT_SCB;
367 break;
368 case NL80211_CHAN_WIDTH_80:
369 /* F = { F1-30, ... F1+30 } => { 0x0000, ... 0x0300} */
370 prim_chan_pos = ((30 + channel_freq - center_freq0) / 20);
371 if (prim_chan_pos > 3) {
372 SLSI_ERR(sdev, "Invalid center_freq0 in chandef : %u, primary channel = %u,"
373 "primary chan pos calculated = %d\n", center_freq0, channel_freq, prim_chan_pos);
374 prim_chan_pos = 0;
375 }
376 prim_chan_pos = 0xFFFF & (prim_chan_pos << 8);
377 chann_info = 80 | prim_chan_pos;
378 break;
379 default:
380 SLSI_WARN(sdev, "Invalid chandef.width(0x%x)\n", width);
381 chann_info = 0;
382 break;
383 }
384
385 SLSI_DBG3(sdev, SLSI_MLME, "channel_width:%u, chann_info:0x%x\n", width, chann_info);
386 return chann_info;
387 }
388
389 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
390 u16 slsi_get_chann_info(struct slsi_dev *sdev, struct cfg80211_chan_def *chandef)
391 {
392 u16 chann_info = 0;
393
394 SLSI_UNUSED_PARAMETER(sdev);
395
396 if (chandef->width == NL80211_CHAN_WIDTH_20 || chandef->width == NL80211_CHAN_WIDTH_20_NOHT) {
397 chann_info = 20;
398 SLSI_DBG3(sdev, SLSI_MLME, "channel_width:%u, chann_info:0x%x\n", chandef->width, chann_info);
399 } else if (chandef->chan) {
400 chann_info = slsi_compute_chann_info(sdev, chandef->width, chandef->center_freq1,
401 chandef->chan->center_freq);
402 }
403 return chann_info;
404 }
405
406 int slsi_check_channelization(struct slsi_dev *sdev, struct cfg80211_chan_def *chandef,
407 int wifi_sharing_channel_switched)
408 {
409 u8 width;
410 struct ieee80211_reg_rule *rule = NULL;
411 struct ieee80211_channel *channel = NULL;
412 u32 ref_flags;
413
414 switch (chandef->width) {
415 case NL80211_CHAN_WIDTH_20:
416 case NL80211_CHAN_WIDTH_20_NOHT:
417 width = 20;
418 break;
419 case NL80211_CHAN_WIDTH_40:
420 width = 40;
421 break;
422 case NL80211_CHAN_WIDTH_80:
423 width = 80;
424 break;
425 default:
426 SLSI_ERR(sdev, "Invalid chandef.width(0x%x)\n", chandef->width);
427 return -EINVAL;
428 }
429
430 channel = ieee80211_get_channel(sdev->wiphy, chandef->chan->center_freq);
431 if (!channel) {
432 SLSI_ERR(sdev, "Invalid channel %d used to start AP. Channel not found\n", chandef->chan->center_freq);
433 return -EINVAL;
434 }
435
436 if (wifi_sharing_channel_switched == 1) {
437 ref_flags = IEEE80211_CHAN_DISABLED
438 #if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13)
439 | IEEE80211_CHAN_PASSIVE_SCAN
440 #endif
441 ;
442 } else {
443 ref_flags = IEEE80211_CHAN_DISABLED |
444 IEEE80211_CHAN_RADAR
445 #if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13)
446 | IEEE80211_CHAN_PASSIVE_SCAN
447 #endif
448 ;
449 }
450
451 if (channel->flags & ref_flags) {
452 SLSI_ERR(sdev, "Invalid channel %d used to start AP\n", chandef->chan->center_freq);
453 return -EINVAL;
454 }
455 rule = slsi_get_reg_rule(MHZ_TO_KHZ(chandef->center_freq1), &sdev->device_config.domain_info);
456 if (!rule) {
457 SLSI_ERR(sdev, "Invalid channel %d used to start AP. No reg rule found for this channel\n", chandef->chan->center_freq);
458 return -EINVAL;
459 }
460
461 if (MHZ_TO_KHZ(width) <= rule->freq_range.max_bandwidth_khz) {
462 u32 width_boundary1, width_boundary2;
463
464 width_boundary1 = MHZ_TO_KHZ(chandef->center_freq1 - width / 2);
465 width_boundary2 = MHZ_TO_KHZ(chandef->center_freq1 + width / 2);
466 if ((width_boundary1 >= rule->freq_range.start_freq_khz) && (width_boundary2 <= rule->freq_range.end_freq_khz))
467 return 0;
468 SLSI_ERR(sdev, "Invalid channel %d used to start AP. Channel not within frequency range of the reg rule\n", chandef->chan->center_freq);
469 return -EINVAL;
470 }
471 return -EINVAL;
472 }
473
474 #else
475 u16 slsi_get_chann_info(struct slsi_dev *sdev, enum nl80211_channel_type channel_type)
476 {
477 u16 chann_info;
478
479 SLSI_UNUSED_PARAMETER(sdev);
480
481 /* Channel Info
482 * bits 0 ~ 7 : Channel Width (5, 10, 20, 40)
483 * bit 8 : Set to 1 if primary channel is greater than secondary channel (HT Minus)
484 */
485 switch (channel_type) {
486 case NL80211_CHAN_NO_HT:
487 case NL80211_CHAN_HT20:
488 chann_info = 20;
489 break;
490 case NL80211_CHAN_HT40MINUS:
491 chann_info = 40 | SLSI_CHANN_INFO_HT_SCB;
492 break;
493 case NL80211_CHAN_HT40PLUS:
494 chann_info = 40;
495 break;
496 default:
497 SLSI_WARN(sdev, "Unknown channel_type: %d\n", channel_type);
498 chann_info = 0;
499 break;
500 }
501
502 SLSI_DBG3(sdev, SLSI_MLME, "channel_type:%d, chann_info:0x%x\n", channel_type, chann_info);
503 return chann_info;
504 }
505
506 int slsi_check_channelization(struct slsi_dev *sdev, enum nl80211_channel_type channel_type)
507 {
508 return 0;
509 }
510
511 #endif
512
513 /* Called in the case of MIB SET errors.
514 * Decode and print a MIB buffer to the log for debug purposes.
515 */
516 static void mib_buffer_dump_to_log(struct slsi_dev *sdev, u8 *mib_buffer, unsigned int mib_buffer_len)
517 {
518 size_t mib_decode_result;
519 size_t offset = 0;
520 struct slsi_mib_entry decoded_mib_value;
521 struct slsi_mib_data mibdata;
522 int error_out_len = mib_buffer_len * 3;
523 int error_out_pos = 0;
524 char *error_out;
525
526 SLSI_UNUSED_PARAMETER(sdev);
527
528 FUNC_ENTER(sdev);
529 SLSI_ERR(sdev, "MIB buffer length: %u. MIB Error (decoded):", mib_buffer_len);
530
531 if (!mib_buffer) {
532 SLSI_ERR(sdev, "MIB buffer pointer is NULL - can not decode MIB keys\n");
533 return;
534 }
535 error_out = kmalloc(error_out_len, GFP_KERNEL);
536
537 while (offset < mib_buffer_len) {
538 error_out_pos = 0;
539 mibdata.data = &mib_buffer[offset];
540 mibdata.dataLength = mib_buffer_len - offset;
541
542 mib_decode_result = slsi_mib_decode(&mibdata, &decoded_mib_value);
543 if (!mib_decode_result) {
544 SLSI_ERR_HEX(sdev, mibdata.data, mibdata.dataLength, "slsi_mib_decode() Failed to Decode:\n");
545 break;
546 }
547
548 offset += mib_decode_result;
549 /* Time for some eye candy - output the decoded MIB key at error level in the log */
550 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "%d", (int)(decoded_mib_value.psid));
551 if (decoded_mib_value.index[0]) {
552 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, ".%d", (int)(decoded_mib_value.index[0]));
553 if (decoded_mib_value.index[1])
554 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, ".%d", (int)(decoded_mib_value.index[1]));
555 }
556
557 switch (decoded_mib_value.value.type) {
558 case SLSI_MIB_TYPE_BOOL:
559 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=%s\n", decoded_mib_value.value.u.boolValue ? "TRUE" : "FALSE");
560 break;
561 case SLSI_MIB_TYPE_UINT:
562 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=%d\n", (int)decoded_mib_value.value.u.uintValue);
563 break;
564 case SLSI_MIB_TYPE_INT:
565 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=%d\n", (int)decoded_mib_value.value.u.intValue);
566 break;
567 case SLSI_MIB_TYPE_OCTET:
568 {
569 u32 i;
570
571 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=[");
572 for (i = 0; i < decoded_mib_value.value.u.octetValue.dataLength; i++)
573 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "%.2X", (int)decoded_mib_value.value.u.octetValue.data[i]);
574 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "]\n");
575 break;
576 }
577 default:
578 error_out_pos += snprintf(error_out + error_out_pos, error_out_len - error_out_pos, "=Can not decode MIB key type\n");
579 break;
580 }
581
582 SLSI_INFO_NODEV("%s", error_out);
583 }
584 kfree(error_out);
585 FUNC_EXIT(sdev);
586 }
587
588 int slsi_mlme_set_ip_address(struct slsi_dev *sdev, struct net_device *dev)
589 {
590 struct sk_buff *req;
591 struct netdev_vif *ndev_vif = netdev_priv(dev);
592 struct sk_buff *cfm;
593 int r = 0;
594 u32 ipaddr;
595 u8 multicast_add[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
596
597 if (slsi_is_test_mode_enabled()) {
598 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_SET_IP_ADDRESS.request\n");
599 return -EOPNOTSUPP;
600 }
601
602 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
603
604 req = fapi_alloc(mlme_set_ip_address_req, MLME_SET_IP_ADDRESS_REQ, ndev_vif->ifnum, sizeof(ndev_vif->ipaddress));
605 if (!req)
606 return -ENOMEM;
607
608 fapi_set_u16(req, u.mlme_set_ip_address_req.ip_version, 4);
609 fapi_set_memcpy(req, u.mlme_set_ip_address_req.multicast_address, multicast_add);
610
611 ipaddr = htonl(be32_to_cpu(ndev_vif->ipaddress));
612 fapi_append_data(req, (const u8 *)(&ipaddr), sizeof(ipaddr));
613
614 SLSI_DBG2(sdev, SLSI_MLME, "slsi_mlme_set_ip_address(vif: %d, IP: %pI4)\n", ndev_vif->ifnum, &ndev_vif->ipaddress);
615 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_IP_ADDRESS_CFM);
616 if (!cfm)
617 return -EIO;
618
619 if (fapi_get_u16(cfm, u.mlme_set_ip_address_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
620 SLSI_NET_ERR(dev, "mlme_set_ip_address_cfm(result:0x%04x) ERROR\n", fapi_get_u16(cfm, u.mlme_set_ip_address_cfm.result_code));
621 r = -EINVAL;
622 }
623
624 slsi_kfree_skb(cfm);
625 return r;
626 }
627
628 #ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6
629
630 int slsi_mlme_set_ipv6_address(struct slsi_dev *sdev, struct net_device *dev)
631 {
632 struct sk_buff *req;
633 struct netdev_vif *ndev_vif = netdev_priv(dev);
634 struct sk_buff *cfm;
635 int r = 0;
636 u8 solicited_node_addr[ETH_ALEN] = { 0x33, 0x33, 0xff, 0x00, 0x00, 0x00 };
637
638 if (slsi_is_test_mode_enabled()) {
639 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_SET_IP_ADDRESS.request\n");
640 return -EOPNOTSUPP;
641 }
642
643 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
644
645 req = fapi_alloc(mlme_set_ip_address_req, MLME_SET_IP_ADDRESS_REQ, ndev_vif->ifnum, 16);
646 if (!req)
647 return -ENOMEM;
648
649 fapi_set_u16(req, u.mlme_set_ip_address_req.ip_version, 6);
650
651 if (ndev_vif->sta.nd_offload_enabled == 1) {
652 slsi_spinlock_lock(&ndev_vif->ipv6addr_lock);
653 memcpy(&solicited_node_addr[3], &ndev_vif->ipv6address.s6_addr[13], 3);
654 slsi_spinlock_unlock(&ndev_vif->ipv6addr_lock);
655
656 fapi_set_memcpy(req, u.mlme_set_ip_address_req.multicast_address, solicited_node_addr);
657 fapi_append_data(req, ndev_vif->ipv6address.s6_addr, 16);
658 SLSI_DBG2(sdev, SLSI_MLME, "mlme_set_ip_address_req(vif: %d, IP: %pI6)\n", ndev_vif->ifnum,
659 &ndev_vif->ipv6address);
660 } else {
661 u8 node_addr_nd_disable[16];
662
663 memset(&node_addr_nd_disable, 0, sizeof(node_addr_nd_disable));
664 fapi_append_data(req, node_addr_nd_disable, 16);
665 SLSI_DBG2(sdev, SLSI_MLME, "mlme_set_ip_address_req(vif: %d, IP-setting ip address to all zeros)\n",
666 ndev_vif->ifnum);
667 }
668
669 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_IP_ADDRESS_CFM);
670 if (!cfm)
671 return -EIO;
672
673 if (fapi_get_u16(cfm, u.mlme_set_ip_address_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
674 SLSI_NET_ERR(dev, "mlme_set_ip_address_cfm(result:0x%04x) ERROR\n",
675 fapi_get_u16(cfm, u.mlme_set_ip_address_cfm.result_code));
676 r = -EINVAL;
677 }
678 slsi_kfree_skb(cfm);
679 return r;
680 }
681 #endif
682
683 int slsi_mlme_set(struct slsi_dev *sdev, struct net_device *dev, u8 *mib, int mib_len)
684 {
685 struct sk_buff *req;
686 struct sk_buff *cfm;
687 int r = 0;
688 u16 ifnum = 0;
689
690 if (dev) {
691 struct netdev_vif *ndev_vif = netdev_priv(dev);
692
693 ifnum = ndev_vif->ifnum;
694 }
695
696 req = fapi_alloc(mlme_set_req, MLME_SET_REQ, ifnum, mib_len);
697 if (!req)
698 return -ENOMEM;
699
700 fapi_append_data(req, mib, mib_len);
701
702 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_CFM);
703 if (!cfm)
704 return -EIO;
705
706 if (fapi_get_datalen(cfm)) {
707 mib_buffer_dump_to_log(sdev, fapi_get_data(cfm), fapi_get_datalen(cfm));
708 r = -EINVAL;
709 }
710
711 slsi_kfree_skb(cfm);
712
713 return r;
714 }
715
716 int slsi_mlme_get(struct slsi_dev *sdev, struct net_device *dev, u8 *mib, int mib_len, u8 *resp,
717 int resp_buf_len, int *resp_len)
718 {
719 struct sk_buff *req;
720 struct sk_buff *err = NULL;
721 struct sk_buff *cfm;
722 int r = 0;
723 u16 ifnum = 0;
724
725 *resp_len = 0;
726
727 if (dev) {
728 struct netdev_vif *ndev_vif = netdev_priv(dev);
729
730 ifnum = ndev_vif->ifnum;
731 }
732 req = fapi_alloc(mlme_get_req, MLME_GET_REQ, ifnum, mib_len);
733 if (!req)
734 return -ENOMEM;
735 fapi_append_data(req, mib, mib_len);
736
737 cfm = slsi_mlme_req_cfm_mib(sdev, dev, req, MLME_GET_CFM, &err);
738 if (!cfm)
739 return -EIO;
740
741 if (err) {
742 SLSI_DBG1(sdev, SLSI_MLME, "ERROR: mlme_get_cfm with mib error\n");
743 mib_buffer_dump_to_log(sdev, fapi_get_data(err), fapi_get_datalen(err));
744 LOG_CONDITIONALLY(fapi_get_datalen(cfm) > resp_buf_len,
745 SLSI_ERR(sdev, "Insufficient resp_buf_len(%d). mlme_get_cfm(%d)\n",
746 resp_buf_len, fapi_get_datalen(cfm)));
747 r = -EINVAL;
748 }
749
750 /* if host has requested for multiple PSIDs in same request, we can get a
751 * combination of error and success
752 */
753 if (fapi_get_datalen(cfm) <= resp_buf_len) {
754 *resp_len = fapi_get_datalen(cfm);
755 memcpy(resp, fapi_get_data(cfm), fapi_get_datalen(cfm));
756 r = 0;
757 } else {
758 SLSI_WARN(sdev, "Insufficient length (%d) to read MIB values, expected =%d\n", resp_buf_len, fapi_get_datalen(cfm));
759 r = -EINVAL;
760 }
761
762 slsi_kfree_skb(err);
763 slsi_kfree_skb(cfm);
764
765 return r;
766 }
767
768 int slsi_mlme_add_vif(struct slsi_dev *sdev, struct net_device *dev, u8 *interface_address, u8 *device_address)
769 {
770 struct netdev_vif *ndev_vif = netdev_priv(dev);
771 struct sk_buff *req;
772 struct sk_buff *cfm;
773 int r = 0, i;
774
775 if (slsi_is_test_mode_enabled()) {
776 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_ADD_VIF.request\n");
777 return -EOPNOTSUPP;
778 }
779
780 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
781
782 /* reset host stats */
783 for (i = 0; i < SLSI_LLS_AC_MAX; i++) {
784 ndev_vif->tx_no_ack[i] = 0;
785 ndev_vif->tx_packets[i] = 0;
786 ndev_vif->rx_packets[i] = 0;
787 }
788 req = fapi_alloc(mlme_add_vif_req, MLME_ADD_VIF_REQ, ndev_vif->ifnum, 0);
789 if (!req)
790 return -ENOMEM;
791 fapi_set_u16(req, u.mlme_add_vif_req.virtual_interface_type, ndev_vif->vif_type);
792 fapi_set_memcpy(req, u.mlme_add_vif_req.interface_address, interface_address);
793 fapi_set_memcpy(req, u.mlme_add_vif_req.device_address, device_address);
794 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_add_vif_req(vif:%d)\n", ndev_vif->ifnum);
795 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_ADD_VIF_CFM);
796 if (!cfm)
797 return -EIO;
798
799 if (fapi_get_u16(cfm, u.mlme_add_vif_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
800 SLSI_NET_ERR(dev, "mlme_add_vif_cfm(result:0x%04x) ERROR\n",
801 fapi_get_u16(cfm, u.mlme_add_vif_cfm.result_code));
802 r = -EINVAL;
803 }
804
805 /* By default firmware vif will be in active mode */
806 ndev_vif->power_mode = FAPI_POWERMANAGEMENTMODE_ACTIVE_MODE;
807
808 slsi_kfree_skb(cfm);
809 return r;
810 }
811
812 void slsi_mlme_del_vif(struct slsi_dev *sdev, struct net_device *dev)
813 {
814 struct netdev_vif *ndev_vif = netdev_priv(dev);
815 struct sk_buff *req;
816 struct sk_buff *cfm;
817
818 if (slsi_is_test_mode_enabled()) {
819 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_DEL_VIF.request\n");
820 return;
821 }
822
823 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
824
825 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_del_vif_req(vif:%d)\n", ndev_vif->ifnum);
826 req = fapi_alloc(mlme_del_vif_req, MLME_DEL_VIF_REQ, ndev_vif->ifnum, 0);
827 if (!req)
828 return;
829
830 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_DEL_VIF_CFM);
831 if (!cfm)
832 return;
833
834 if (fapi_get_u16(cfm, u.mlme_del_vif_cfm.result_code) != FAPI_RESULTCODE_SUCCESS)
835 SLSI_NET_ERR(dev, "mlme_del_vif_cfm(result:0x%04x) ERROR\n",
836 fapi_get_u16(cfm, u.mlme_del_vif_cfm.result_code));
837
838 if (((ndev_vif->iftype == NL80211_IFTYPE_P2P_CLIENT) || (ndev_vif->iftype == NL80211_IFTYPE_STATION)) &&
839 (ndev_vif->delete_probe_req_ies)) {
840 kfree(ndev_vif->probe_req_ies);
841 ndev_vif->probe_req_ies = NULL;
842 ndev_vif->probe_req_ie_len = 0;
843 ndev_vif->delete_probe_req_ies = false;
844 }
845 if (SLSI_IS_VIF_INDEX_P2P(ndev_vif))
846 ndev_vif->drv_in_p2p_procedure = false;
847
848 slsi_kfree_skb(cfm);
849 }
850
851 #ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON
852 int slsi_mlme_set_forward_beacon(struct slsi_dev *sdev, struct net_device *dev, int action)
853 {
854 struct netdev_vif *ndev_vif = netdev_priv(dev);
855 struct sk_buff *req;
856 struct sk_buff *cfm;
857
858 if (slsi_is_test_mode_enabled()) {
859 SLSI_NET_INFO(dev, "wlanlite does not support mlme_forward_bacon_req\n");
860 return -EOPNOTSUPP;
861 }
862
863 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_forward_beacon_req(action = %s(%d))\n", action ? "start" : "stop", action);
864
865 req = fapi_alloc(mlme_forward_beacon_req, MLME_FORWARD_BEACON_REQ, ndev_vif->ifnum, 0);
866 if (!req) {
867 SLSI_NET_ERR(dev, "fapi alloc for mlme_forward_beacon_req is failed\n");
868 return -ENOMEM;
869 }
870
871 fapi_set_u16(req, u.mlme_forward_beacon_req.wips_action, action);
872
873 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_FORWARD_BEACON_CFM);
874 if (!cfm) {
875 SLSI_NET_ERR(dev, "receiving mlme_forward_beacon_cfm is failed\n");
876 return -EIO;
877 }
878
879 if (fapi_get_u16(cfm, u.mlme_forward_beacon_cfm.result_code) != FAPI_RESULTCODE_HOST_REQUEST_SUCCESS) {
880 SLSI_NET_ERR(dev, "mlme_forward_beacon_cfm(result:0x%04x) ERROR\n",
881 fapi_get_u16(cfm, u.mlme_forward_beacon_cfm.result_code));
882 return -EINVAL;
883 }
884
885 ndev_vif->is_wips_running = (action ? true : false);
886
887 slsi_kfree_skb(cfm);
888 return 0;
889 }
890 #endif
891
892 int slsi_mlme_set_channel(struct slsi_dev *sdev, struct net_device *dev, struct ieee80211_channel *chan, u16 duration, u16 interval, u16 count)
893 {
894 struct netdev_vif *ndev_vif = netdev_priv(dev);
895 struct sk_buff *req;
896 struct sk_buff *cfm;
897 int r = 0;
898
899 if (slsi_is_test_mode_enabled()) {
900 SLSI_NET_INFO(dev, "wlanlite does not support MLME_SET_CHANNEL.request\n");
901 return -EOPNOTSUPP;
902 }
903
904 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
905
906 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_channel_req(freq:%u, duration:%u, interval:%u, count:%u)\n", chan->center_freq, duration, interval, count);
907
908 req = fapi_alloc(mlme_set_channel_req, MLME_SET_CHANNEL_REQ, ndev_vif->ifnum, 0);
909 if (!req)
910 return -ENOMEM;
911
912 fapi_set_u16(req, u.mlme_set_channel_req.availability_duration, duration);
913 fapi_set_u16(req, u.mlme_set_channel_req.availability_interval, interval);
914 fapi_set_u16(req, u.mlme_set_channel_req.count, count);
915 fapi_set_u16(req, u.mlme_set_channel_req.channel_frequency, SLSI_FREQ_HOST_TO_FW(chan->center_freq));
916
917 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_CHANNEL_CFM);
918 if (!cfm)
919 return -EIO;
920
921 if (fapi_get_u16(cfm, u.mlme_set_channel_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
922 SLSI_NET_ERR(dev, "mlme_set_channel_cfm(result:0x%04x) ERROR\n",
923 fapi_get_u16(cfm, u.mlme_set_channel_cfm.result_code));
924 r = -EINVAL;
925 }
926
927 slsi_kfree_skb(cfm);
928 return r;
929 }
930
931 int slsi_mlme_unset_channel_req(struct slsi_dev *sdev, struct net_device *dev)
932 {
933 struct netdev_vif *ndev_vif = netdev_priv(dev);
934 struct sk_buff *req;
935 struct sk_buff *cfm;
936 int r = 0;
937
938 SLSI_NET_DBG3(dev, SLSI_MLME, "slsi_mlme_unset_channel_req\n");
939
940 req = fapi_alloc(mlme_unset_channel_req, MLME_UNSET_CHANNEL_REQ, ndev_vif->ifnum, 0);
941
942 if (!req)
943 return -ENOMEM;
944
945 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_UNSET_CHANNEL_CFM);
946
947 if (!cfm)
948 return -EIO;
949
950 if (fapi_get_u16(cfm, u.mlme_unset_channel_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
951 SLSI_NET_ERR(dev, "mlme_unset_channel_cfm(result:0x%04x) ERROR\n",
952 fapi_get_u16(cfm, u.mlme_unset_channel_cfm.result_code));
953 r = -EINVAL;
954 }
955
956 slsi_kfree_skb(cfm);
957 return r;
958 }
959
960 void slsi_ap_obss_scan_done_ind(struct net_device *dev, struct netdev_vif *ndev_vif)
961 {
962 struct sk_buff *scan_res;
963 u16 scan_id = SLSI_SCAN_HW_ID;
964
965 SLSI_UNUSED_PARAMETER(dev);
966
967 SLSI_NET_DBG1(dev, SLSI_MLME, "Scan before AP start completed\n");
968
969 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
970 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex));
971 SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex);
972
973 scan_res = slsi_dequeue_cached_scan_result(&ndev_vif->scan[scan_id], NULL);
974 while (scan_res) {
975 struct ieee80211_mgmt *mgmt = fapi_get_mgmt(scan_res);
976 size_t mgmt_len = fapi_get_mgmtlen(scan_res);
977 size_t ie_len = mgmt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); /* ieee80211_mgmt structure is similar for Probe Response and Beacons */
978
979 SLSI_NET_DBG4(dev, SLSI_MLME, "OBSS scan result (scan_id:%d, %pM, freq:%d, rssi:%d, ie_len = %zu)\n",
980 fapi_get_u16(scan_res, u.mlme_scan_ind.scan_id),
981 fapi_get_mgmt(scan_res)->bssid,
982 fapi_get_u16(scan_res, u.mlme_scan_ind.channel_frequency) / 2,
983 fapi_get_s16(scan_res, u.mlme_scan_ind.rssi),
984 ie_len);
985
986 if (!cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, mgmt->u.beacon.variable, ie_len)) {
987 SLSI_NET_DBG1(dev, SLSI_MLME, "Non HT BSS detected on primary channel\n");
988 ndev_vif->ap.non_ht_bss_present = true;
989 }
990
991 slsi_kfree_skb(scan_res);
992 scan_res = slsi_dequeue_cached_scan_result(&ndev_vif->scan[scan_id], NULL);
993 }
994 SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex);
995 }
996
997 /* Null check for cfm done in caller function */
998 static bool slsi_scan_cfm_validate(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm)
999 {
1000 bool r = true;
1001
1002 if (fapi_get_u16(cfm, u.mlme_add_scan_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
1003 SLSI_ERR_NODEV("mlme_add_scan_cfm(result:0x%04x) ERROR\n",
1004 fapi_get_u16(cfm, u.mlme_add_scan_cfm.result_code));
1005 r = false;
1006 }
1007
1008 slsi_kfree_skb(cfm);
1009 return r;
1010 }
1011
1012 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
1013 int slsi_mlme_append_gscan_channel_list(struct slsi_dev *sdev,
1014 struct net_device *dev,
1015 struct sk_buff *req,
1016 struct slsi_nl_bucket_param *nl_bucket)
1017 {
1018 u16 channel_freq;
1019 u8 i;
1020 u8 *p;
1021 const u8 channels_list_ie_header[] = {
1022 0xDD, /* Element ID: Vendor Specific */
1023 0x05, /* Length: actual length will be updated later */
1024 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1025 0x01, /* OUI Type: Scan parameters */
1026 0x02 /* OUI Subtype: channel list */
1027 };
1028 u8 *channels_list_ie = fapi_append_data(req, channels_list_ie_header, sizeof(channels_list_ie_header));
1029
1030 if (!channels_list_ie) {
1031 SLSI_WARN(sdev, "channel list IE append failed\n");
1032 slsi_kfree_skb(req);
1033 return -EINVAL;
1034 }
1035
1036 if (nl_bucket->band == WIFI_BAND_UNSPECIFIED)
1037 /* channel list is added only if band is UNSPECIFIED */
1038 for (i = 0; i < nl_bucket->num_channels; i++) {
1039 p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE);
1040 if (!p) {
1041 SLSI_ERR(sdev, "chan desc[%d] append failed\n", i);
1042 slsi_kfree_skb(req);
1043 return -EINVAL;
1044 }
1045 channel_freq = SLSI_FREQ_HOST_TO_FW(nl_bucket->channels[i].channel);
1046 channel_freq = cpu_to_le16(channel_freq);
1047 memcpy(p, &channel_freq, sizeof(channel_freq));
1048 p[2] = FAPI_SCANPOLICY_ANY_RA;
1049 channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE; /* Length */
1050 }
1051 else {
1052 p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE);
1053 if (!p) {
1054 SLSI_ERR(sdev, "chan desc(band specific)append failed\n");
1055 slsi_kfree_skb(req);
1056 return -EINVAL;
1057 }
1058 /* Channel frequency set to 0 for all channels allowed by the corresponding regulatory domain and scan policy */
1059 channel_freq = 0;
1060 memcpy(p, &channel_freq, sizeof(channel_freq));
1061 p[2] = slsi_gscan_get_scan_policy(nl_bucket->band);
1062 channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE;
1063 }
1064
1065 return 0;
1066 }
1067 #endif
1068
1069 static int slsi_mlme_append_channel_list(struct slsi_dev *sdev,
1070 struct net_device *dev,
1071 struct sk_buff *req,
1072 u32 num_channels,
1073 struct ieee80211_channel *channels[],
1074 u16 scan_type,
1075 bool passive_scan)
1076 {
1077 int chann;
1078 u16 freq_fw_unit;
1079 u8 i;
1080 int n_valid_channels = 0;
1081 u8 *p;
1082
1083 const u8 channels_list_ie_header[] = {
1084 0xDD, /* Element ID: vendor specific */
1085 0x05, /* Length: actual length will be updated later */
1086 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1087 0x01, /* OUI Type: scan parameters */
1088 0x02 /* OUI Subtype: channel list */
1089 };
1090
1091 u8 *channels_list_ie = fapi_append_data(req, channels_list_ie_header, sizeof(channels_list_ie_header));
1092
1093 if (!channels_list_ie) {
1094 SLSI_WARN(sdev, "channel list IE append failed\n");
1095 slsi_kfree_skb(req);
1096 return -EINVAL;
1097 }
1098
1099 /* For P2P Full Scan, Setting Channel Frequency = 0x0000, Scan Policy = 2.4GHz, 5GHz and Non-Dfs. */
1100 if (scan_type == FAPI_SCANTYPE_P2P_SCAN_FULL) {
1101 p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE);
1102 if (!p) {
1103 SLSI_WARN(sdev, "scan channel descriptor append failed\n");
1104 slsi_kfree_skb(req);
1105 return -EINVAL;
1106 }
1107 p[0] = 0;
1108 p[1] = 0;
1109 p[2] = FAPI_SCANPOLICY_2_4GHZ | FAPI_SCANPOLICY_5GHZ | FAPI_SCANPOLICY_NON_DFS;
1110 channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE;
1111 return 0;
1112 }
1113
1114 for (i = 0; i < num_channels; i++) {
1115 chann = channels[i]->hw_value & 0xFF;
1116
1117 if (sdev->device_config.supported_band) {
1118 if (channels[i]->band == NL80211_BAND_2GHZ && sdev->device_config.supported_band != SLSI_FREQ_BAND_2GHZ)
1119 continue;
1120 if (channels[i]->band == NL80211_BAND_5GHZ && sdev->device_config.supported_band != SLSI_FREQ_BAND_5GHZ)
1121 continue;
1122 }
1123
1124 n_valid_channels++;
1125 p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE);
1126 if (!p) {
1127 SLSI_WARN(sdev, "scan channel descriptor append failed\n");
1128 slsi_kfree_skb(req);
1129 return -EINVAL;
1130 }
1131 freq_fw_unit = 2 * ieee80211_channel_to_frequency(chann, (chann <= 14) ?
1132 NL80211_BAND_2GHZ : NL80211_BAND_5GHZ);
1133 freq_fw_unit = cpu_to_le16(freq_fw_unit);
1134 memcpy(p, &freq_fw_unit, sizeof(freq_fw_unit));
1135
1136 if (passive_scan && (scan_type != FAPI_SCANTYPE_AP_AUTO_CHANNEL_SELECTION))
1137 p[2] = FAPI_SCANPOLICY_PASSIVE;
1138 else
1139 p[2] = 0;
1140
1141 channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE;
1142 }
1143 if (n_valid_channels == 0) {
1144 SLSI_NET_ERR(dev, "no valid channels to Scan\n");
1145 slsi_kfree_skb(req);
1146 return -EINVAL;
1147 }
1148 return 0;
1149 }
1150
1151 static inline int slsi_set_scan_params(
1152 struct net_device *dev,
1153 u16 scan_id,
1154 u16 scan_type,
1155 u16 report_mode,
1156 int num_ssids,
1157 struct cfg80211_ssid *ssids,
1158 struct sk_buff *req)
1159 {
1160 u8 *p = NULL;
1161 u8 i;
1162 struct cfg80211_ssid *pssid = ssids;
1163 #ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
1164 struct netdev_vif *netdev_vif = netdev_priv(dev);
1165 struct slsi_dev *sdev = netdev_vif->sdev;
1166 #endif
1167
1168 fapi_set_u16(req, u.mlme_add_scan_req.scan_id, scan_id);
1169 fapi_set_u16(req, u.mlme_add_scan_req.scan_type, scan_type);
1170 fapi_set_u16(req, u.mlme_add_scan_req.report_mode_bitmap, report_mode);
1171
1172
1173 #ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
1174 if (sdev->scan_addr_set && slsi_dev_mac_randomisation_support()) //IKSAMP-1972
1175 fapi_set_memcpy(req, u.mlme_add_scan_req.device_address, sdev->scan_mac_addr);
1176 else
1177 #endif
1178 fapi_set_memcpy(req, u.mlme_add_scan_req.device_address, dev->dev_addr);
1179
1180 for (i = 0; i < num_ssids; i++, pssid++) {
1181 p = fapi_append_data(req, NULL, 2 + pssid->ssid_len);
1182 if (!p) {
1183 slsi_kfree_skb(req);
1184 SLSI_NET_WARN(dev, "fail to append SSID element to scan request\n");
1185 return -EINVAL;
1186 }
1187
1188 *p++ = WLAN_EID_SSID;
1189 *p++ = pssid->ssid_len;
1190
1191 if (pssid->ssid_len)
1192 memcpy(p, pssid->ssid, pssid->ssid_len);
1193 }
1194 return 0;
1195 }
1196
1197 #define SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM 7
1198 int slsi_mlme_add_sched_scan(struct slsi_dev *sdev,
1199 struct net_device *dev,
1200 struct cfg80211_sched_scan_request *request,
1201 const u8 *ies,
1202 u16 ies_len)
1203 {
1204 struct netdev_vif *ndev_vif = netdev_priv(dev);
1205 struct sk_buff *req;
1206 struct sk_buff *rx;
1207 int r = 0;
1208 size_t alloc_data_size = 0;
1209 u32 i, j;
1210 u32 num_ssid_filter_elements = 0;
1211
1212 /* Scan Timing IE: default values */
1213 u8 scan_timing_ie[] = {
1214 0xdd, /* Element ID: Vendor Specific */
1215 0x11, /* Length */
1216 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1217 0x01, /* OUI Type: Scan parameters */
1218 0x01, /* OUI Subtype: Scan timing */
1219 0x00, 0x00, 0x00, 0x00, /* Min_Period: filled later in the function */
1220 0x00, 0x00, 0x00, 0x00, /* Max_Period: filled later in the function */
1221 /* BEGIN IKSAMP-7392, optimize pno scanning interval */
1222 0x0a, /* Exponent */
1223 0x07, /* Step count */
1224 /* END IKSAMP-7392 */
1225 0x00, 0x01 /* Skip first period: true for scheduled scans*/
1226 };
1227
1228 u8 ssid_filter_ie_hdr[] = {
1229 0xdd, /* Element ID: Vendor Specific */
1230 0x05, /* Length */
1231 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1232 0x01, /* OUI Type: Scan parameters */
1233 0x04 /* OUI Subtype: SSID Filter */
1234 };
1235
1236 if (slsi_is_test_mode_enabled()) {
1237 SLSI_NET_WARN(dev, "not supported in WlanLite mode\n");
1238 return -EOPNOTSUPP;
1239 }
1240
1241 if (WARN_ON(!(dev->dev_addr)))
1242 return -EINVAL;
1243
1244 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex));
1245
1246 #ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
1247 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
1248 if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
1249 if (sdev->fw_mac_randomization_enabled) {
1250 memcpy(sdev->scan_mac_addr, request->mac_addr, ETH_ALEN);
1251 r = slsi_set_mac_randomisation_mask(sdev, request->mac_addr_mask);
1252 if (!r)
1253 sdev->scan_addr_set = 1;
1254 } else {
1255 SLSI_NET_INFO(dev, "Mac Randomization is not enabled in Firmware\n");
1256 sdev->scan_addr_set = 0;
1257 }
1258 }
1259 #endif
1260 #endif
1261
1262 alloc_data_size += sizeof(scan_timing_ie) + ies_len + SLSI_SCAN_PRIVATE_IE_CHANNEL_LIST_HEADER_LEN +
1263 (request->n_channels * SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE);
1264
1265 for (i = 0; i < request->n_ssids; i++) {
1266 /* 2 bytes for SSID EID and length field + variable length SSID */
1267 alloc_data_size += (2 + request->ssids[i].ssid_len);
1268 }
1269
1270 if (request->n_match_sets) {
1271 num_ssid_filter_elements = (request->n_match_sets / SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM) + 1;
1272 /* EID(1) + len(1) + oui(3) + type/subtype(2) + 7 ssid descriptors(7 * 33) */
1273 alloc_data_size += 238 * num_ssid_filter_elements;
1274 }
1275
1276 req = fapi_alloc(mlme_add_scan_req, MLME_ADD_SCAN_REQ, 0, alloc_data_size);
1277 if (!req)
1278 return -ENOMEM;
1279
1280 r = slsi_set_scan_params(dev, (ndev_vif->ifnum << 8 | SLSI_SCAN_SCHED_ID),
1281 FAPI_SCANTYPE_SCHEDULED_SCAN,
1282 FAPI_REPORTMODE_REAL_TIME,
1283 request->n_ssids,
1284 request->ssids,
1285 req);
1286 if (r)
1287 return r;
1288
1289 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
1290 // BEGIN IKSAMP-7392, optimize pno scanning interval
1291 SLSI_U32_TO_BUFF_LE(48 * 1000 * 1000, &scan_timing_ie[7]);
1292 SLSI_U32_TO_BUFF_LE(500 * 1000 * 1000, &scan_timing_ie[11]);
1293 // END IKSAMP-7392
1294 #else
1295 SLSI_U32_TO_BUFF_LE(request->interval * 1000, &scan_timing_ie[7]);
1296 SLSI_U32_TO_BUFF_LE(request->interval * 1000, &scan_timing_ie[11]);
1297 #endif
1298
1299 fapi_append_data(req, scan_timing_ie, sizeof(scan_timing_ie));
1300 fapi_append_data(req, ies, ies_len);
1301
1302 if (request->n_match_sets) {
1303 struct cfg80211_match_set *match_sets = request->match_sets;
1304 u8 *ssid_filter_ie;
1305
1306 for (j = 0; j < num_ssid_filter_elements; j++) {
1307 ssid_filter_ie = fapi_append_data(req, ssid_filter_ie_hdr, sizeof(ssid_filter_ie_hdr));
1308 if (!ssid_filter_ie) {
1309 slsi_kfree_skb(req);
1310 SLSI_ERR(sdev, "ssid_filter_ie append failed\n");
1311 return -EIO;
1312 }
1313 for (i = 0; i < SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM; i++, match_sets++) {
1314 if ((j * SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM) + i >= request->n_match_sets)
1315 break;
1316 SLSI_NET_DBG2(dev, SLSI_MLME, "SSID: %.*s",
1317 match_sets->ssid.ssid_len, match_sets->ssid.ssid);
1318 ssid_filter_ie[1] += (1 + match_sets->ssid.ssid_len);
1319 fapi_append_data(req, &match_sets->ssid.ssid_len, 1);
1320 fapi_append_data(req, match_sets->ssid.ssid, match_sets->ssid.ssid_len);
1321 }
1322 }
1323 }
1324
1325 if (request->n_channels) {
1326 r = slsi_mlme_append_channel_list(sdev, dev, req, request->n_channels, request->channels,
1327 FAPI_SCANTYPE_SCHEDULED_SCAN, request->n_ssids == 0);
1328 if (r)
1329 return r;
1330 }
1331
1332 rx = slsi_mlme_req_cfm(sdev, NULL, req, MLME_ADD_SCAN_CFM);
1333 if (!rx)
1334 return -EIO;
1335
1336 if (fapi_get_u16(rx, u.mlme_add_scan_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
1337 SLSI_NET_ERR(dev, "mlme_add_scan_cfm(result:0x%04x) ERROR\n",
1338 fapi_get_u16(rx, u.mlme_add_scan_cfm.result_code));
1339 r = -EINVAL;
1340 }
1341
1342 slsi_kfree_skb(rx);
1343 return r;
1344 }
1345
1346 int slsi_mlme_add_scan(
1347 struct slsi_dev *sdev,
1348 struct net_device *dev,
1349 u16 scan_type,
1350 u16 report_mode,
1351 u32 n_ssids,
1352 struct cfg80211_ssid *ssids,
1353 u32 n_channels,
1354 struct ieee80211_channel *channels[],
1355 void *gscan,
1356 const u8 *ies,
1357 u16 ies_len,
1358 bool wait_for_ind)
1359 {
1360 struct netdev_vif *ndev_vif = netdev_priv(dev);
1361 struct sk_buff *req;
1362 struct sk_buff *rx;
1363 int r = 0;
1364 size_t alloc_data_size = 0;
1365 u32 i;
1366
1367 /* Scan Timing IE: default values */
1368 u8 scan_timing_ie[] = {
1369 0xdd, /* Element ID: Vendor Specific */
1370 0x11, /* Length */
1371 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1372 0x01, /* OUI Type: Scan parameters */
1373 0x01, /* OUI Subtype: Scan timing */
1374 0x00, 0x00, 0x00, 0x00, /* Min_Period: filled later in the function */
1375 0x00, 0x00, 0x00, 0x00, /* Max_Period: filled later in the function */
1376 0x00, /* Exponent */
1377 0x00, /* Step count */
1378 0x00, 0x00 /* Skip first period: false */
1379 };
1380
1381 if (slsi_is_test_mode_enabled()) {
1382 SLSI_NET_WARN(dev, "not supported in WlanLite mode\n");
1383 return -EOPNOTSUPP;
1384 }
1385
1386 if (WARN_ON(!(dev->dev_addr)))
1387 return -EINVAL;
1388
1389 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->scan_mutex));
1390 SLSI_INFO(sdev, "scan started for id:0x%x, n_channels:%d, n_ssids:%d, scan_type:%d\n",
1391 (ndev_vif->ifnum << 8 | SLSI_SCAN_HW_ID), n_channels, n_ssids, scan_type);
1392
1393 alloc_data_size += sizeof(scan_timing_ie) +
1394 ies_len +
1395 (SLSI_SCAN_PRIVATE_IE_CHANNEL_LIST_HEADER_LEN + (n_channels * SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE));
1396
1397 for (i = 0; i < n_ssids; i++)
1398 alloc_data_size += 2 + ssids[i].ssid_len; /* 2: SSID EID + len */
1399
1400 req = fapi_alloc(mlme_add_scan_req, MLME_ADD_SCAN_REQ, 0, alloc_data_size);
1401 if (!req)
1402 return -ENOMEM;
1403
1404 if (!gscan) {
1405 r = slsi_set_scan_params(
1406 dev,
1407 (ndev_vif->ifnum << 8 | SLSI_SCAN_HW_ID),
1408 scan_type,
1409 report_mode,
1410 n_ssids,
1411 ssids,
1412 req);
1413 if (r)
1414 return r;
1415
1416 fapi_append_data(req, scan_timing_ie, sizeof(scan_timing_ie));
1417 fapi_append_data(req, ies, ies_len);
1418
1419 if (n_channels) {
1420 r = slsi_mlme_append_channel_list(sdev, dev, req, n_channels, channels, scan_type,
1421 n_ssids == 0);
1422 if (r)
1423 return r;
1424 }
1425 }
1426 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
1427 else {
1428 struct slsi_gscan_param *gscan_param = (struct slsi_gscan_param *)gscan;
1429
1430 r = slsi_set_scan_params(
1431 dev,
1432 gscan_param->bucket->scan_id,
1433 scan_type,
1434 report_mode,
1435 n_ssids,
1436 ssids,
1437 req);
1438 if (r)
1439 return r;
1440
1441 SLSI_U32_TO_BUFF_LE((gscan_param->nl_bucket->period * 1000), &scan_timing_ie[7]);
1442 if (gscan_param->nl_bucket->exponent) {
1443 SLSI_U32_TO_BUFF_LE((gscan_param->nl_bucket->max_period * 1000), &scan_timing_ie[11]);
1444 scan_timing_ie[15] = (u8)gscan_param->nl_bucket->exponent;
1445 scan_timing_ie[16] = (u8)gscan_param->nl_bucket->step_count;
1446 }
1447 fapi_append_data(req, scan_timing_ie, sizeof(scan_timing_ie));
1448
1449 r = slsi_mlme_append_gscan_channel_list(sdev, dev, req, gscan_param->nl_bucket);
1450 if (r)
1451 return r;
1452 }
1453 #endif
1454 if (wait_for_ind) {
1455 /* Use the Global sig_wait not the Interface specific for Scan Req */
1456 rx = slsi_mlme_req_cfm_ind(sdev, NULL, req, MLME_ADD_SCAN_CFM, MLME_SCAN_DONE_IND, slsi_scan_cfm_validate);
1457 if (!rx)
1458 return -EIO;
1459 SLSI_NET_DBG3(dev, SLSI_MLME, "mlme_scan_done_ind()\n");
1460
1461 /* slsi_mlme_add_scan is a generic definition for multiple handlers
1462 * Any added functionality, if not generic, should not be defined here.
1463 * It should be a part of calling function.
1464 */
1465 } else {
1466 /* Use the Global sig_wait not the Interface specific for Scan Req */
1467 rx = slsi_mlme_req_cfm(sdev, NULL, req, MLME_ADD_SCAN_CFM);
1468 if (!rx)
1469 return -EIO;
1470 if (fapi_get_u16(rx, u.mlme_add_scan_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
1471 SLSI_NET_ERR(dev, "mlme_add_scan_cfm(result:0x%04x) ERROR\n",
1472 fapi_get_u16(rx, u.mlme_add_scan_cfm.result_code));
1473 r = -EINVAL;
1474 }
1475 }
1476 slsi_kfree_skb(rx);
1477 return r;
1478 }
1479
1480 int slsi_mlme_del_scan(struct slsi_dev *sdev, struct net_device *dev, u16 scan_id, bool scan_timed_out)
1481 {
1482 struct netdev_vif *ndev_vif = netdev_priv(dev);
1483 struct sk_buff *req;
1484 struct sk_buff *cfm;
1485 int r = 0;
1486
1487 if (slsi_is_test_mode_enabled()) {
1488 SLSI_NET_WARN(dev, "not supported in WlanLite mode\n");
1489 return -EOPNOTSUPP;
1490 }
1491
1492 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_del_scan_req(scan_id:%d)\n", scan_id);
1493
1494 if ((scan_id & 0xFF) == SLSI_SCAN_HW_ID && ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req && !scan_timed_out)
1495 cancel_delayed_work(&ndev_vif->scan_timeout_work);
1496
1497 req = fapi_alloc(mlme_del_scan_req, MLME_DEL_SCAN_REQ, 0, 0);
1498 if (!req)
1499 return -ENOMEM;
1500 fapi_set_u16(req, u.mlme_del_scan_req.scan_id, scan_id);
1501
1502 /* Use the Global sig_wait not the Interface specific for Scan Req */
1503 cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_DEL_SCAN_CFM);
1504 if (!cfm)
1505 return -EIO;
1506
1507 if (fapi_get_u16(cfm, u.mlme_del_scan_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
1508 SLSI_NET_ERR(dev, "mlme_del_scan_cfm(result:0x%04x) ERROR\n",
1509 fapi_get_u16(cfm, u.mlme_del_scan_cfm.result_code));
1510 r = -EINVAL;
1511 }
1512
1513 slsi_kfree_skb(cfm);
1514 return r;
1515 }
1516
1517 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1518 static void slsi_ap_add_ext_capab_ie(struct sk_buff *req, struct netdev_vif *ndev_vif, const u8 *prev_ext)
1519 {
1520 u8 ext_capa_ie[SLSI_AP_EXT_CAPAB_IE_LEN_MAX];
1521 int i;
1522 int prev_len = 0;
1523
1524 ext_capa_ie[0] = WLAN_EID_EXT_CAPABILITY;
1525 ext_capa_ie[1] = SLSI_AP_EXT_CAPAB_IE_LEN_MAX - 1 - 1;
1526 if (prev_ext) {
1527 prev_len = prev_ext[1];
1528 for (i = 2; i < prev_len + 2; i++)
1529 ext_capa_ie[i] = prev_ext[i];
1530 }
1531 for (i = prev_len + 2; i < SLSI_AP_EXT_CAPAB_IE_LEN_MAX; i++)
1532 ext_capa_ie[i] = 0x00;
1533 SLSI_DBG3(ndev_vif->sdev, SLSI_MLME, "New Ext capab Added\n");
1534 /* For VHT, set the Operating Mode Notification field - Bit 62 (8th Octet) */
1535 ext_capa_ie[9] |= 0x40;
1536
1537 fapi_append_data(req, &ext_capa_ie[0], SLSI_AP_EXT_CAPAB_IE_LEN_MAX);
1538 }
1539 #endif
1540
1541 static int slsi_prepare_country_ie(struct slsi_dev *sdev, u16 center_freq, u8 *country_ie, u8 **new_country_ie)
1542 {
1543 struct ieee80211_supported_band band;
1544 struct ieee80211_reg_rule *rule;
1545 struct ieee80211_channel *channels;
1546 u8 *ie;
1547 u8 offset = 0;
1548 int i;
1549
1550 /* Select frequency band */
1551 if (center_freq < 5180)
1552 band = slsi_band_2ghz;
1553 else
1554 band = slsi_band_5ghz;
1555
1556 /* Allocate memory for the new country IE - EID(1) + Len(1) + CountryString(3) + ChannelInfo (n * 3) */
1557 ie = kmalloc(5 + (band.n_channels * 3), GFP_KERNEL);
1558 if (!ie) {
1559 SLSI_ERR(sdev, "Failed to allocate memory\n");
1560 return -ENOMEM;
1561 }
1562
1563 /* Preapre the new country IE */
1564 ie[offset++] = country_ie[0]; /* Element IE */
1565 ie[offset++] = 0; /* IE Length - initialized at the end of this function */
1566 ie[offset++] = sdev->device_config.domain_info.regdomain->alpha2[0]; /* Country code */
1567 ie[offset++] = sdev->device_config.domain_info.regdomain->alpha2[1]; /* Country code */
1568 ie[offset++] = country_ie[4]; /* CountryString: 3rd octet */
1569
1570 channels = band.channels;
1571 for (i = 0; i < band.n_channels; i++, channels++) {
1572 /* Get the regulatory rule for the channel */
1573 rule = slsi_get_reg_rule(MHZ_TO_KHZ(channels->center_freq), &sdev->device_config.domain_info);
1574 if (rule) {
1575 ie[offset++] = channels->hw_value; /* Channel number */
1576 ie[offset++] = 1; /* Number of channels */
1577 ie[offset++] = MBM_TO_DBM(rule->power_rule.max_eirp); /* Max TX power */
1578 }
1579 }
1580
1581 ie[1] = offset - 2; /* Length of IE */
1582 *new_country_ie = ie;
1583
1584 return 0;
1585 }
1586
1587 int slsi_modify_ies(struct net_device *dev, u8 eid, u8 *ies, int ies_len, u8 ie_index, u8 ie_value)
1588 {
1589 u8 *ie;
1590
1591 SLSI_NET_DBG1(dev, SLSI_MLME, "eid: %d, ie_value = 0x%x\n", eid, ie_value);
1592
1593 ie = (u8 *)cfg80211_find_ie(eid, ies, ies_len);
1594 if (ie) {
1595 switch (eid) {
1596 case WLAN_EID_HT_CAPABILITY:
1597 case WLAN_EID_VHT_CAPABILITY:
1598 ie[ie_index] |= ie_value;
1599 break;
1600 case WLAN_EID_DS_PARAMS:
1601 case WLAN_EID_HT_OPERATION:
1602 if (ie_index == 2)
1603 ie[ie_index] = ie_value;
1604 else
1605 ie[ie_index] |= ie_value;
1606 break;
1607 default:
1608 SLSI_NET_WARN(dev, "slsi_modify_ies: IE type mismatch : %d\n", eid);
1609 return false;
1610 }
1611 return true;
1612 }
1613 SLSI_NET_WARN(dev, "slsi_modify_ies: IE not found : %d\n", eid);
1614 return false;
1615 }
1616
1617 static void slsi_mlme_start_prepare_ies(struct sk_buff *req, struct netdev_vif *ndev_vif, struct cfg80211_ap_settings *settings, const u8 *wpa_ie_pos, const u8 *wmm_ie_pos)
1618 {
1619 const u8 *wps_ie, *vht_capab_ie, *tail_pos = NULL, *ext_capab_ie;
1620 size_t beacon_ie_len = 0, tail_length = 0;
1621 u8 *country_ie;
1622 const u8 *beacon_tail = settings->beacon.tail;
1623 size_t beacon_tail_len = settings->beacon.tail_len;
1624
1625 /**
1626 * Channel list of Country IE prepared by hostapd is wrong, so driver needs remove the existing country IE and prepare correct one.
1627 * Hostapd adds country IE at the beginning of the tail, beacon_tail is moved to the next IE to avoid the default county IE.
1628 */
1629 country_ie = (u8 *)cfg80211_find_ie(WLAN_EID_COUNTRY, beacon_tail, beacon_tail_len);
1630 if (country_ie) {
1631 u8 *new_country_ie = NULL;
1632
1633 SLSI_DBG3(ndev_vif->sdev, SLSI_MLME, "Country IE found, length = %d", country_ie[1]);
1634
1635 /* Prepare the new country IE */
1636 if (slsi_prepare_country_ie(ndev_vif->sdev, ndev_vif->chan->center_freq, country_ie, &new_country_ie) != 0)
1637 SLSI_ERR(ndev_vif->sdev, "Failed to prepare country IE");
1638
1639 /* Add the new country IE */
1640 if (new_country_ie) {
1641 /* new_country_ie[1] ontains the length of IE */
1642 fapi_append_data(req, new_country_ie, (new_country_ie[1] + 2));
1643
1644 /* Free the memory allocated for the new country IE */
1645 kfree(new_country_ie);
1646
1647 /* Remove the default country IE from the beacon_tail */
1648 beacon_tail += (country_ie[1] + 2);
1649 beacon_tail_len -= (country_ie[1] + 2);
1650 }
1651 }
1652
1653 /* Modify HT IE based on OBSS scan data */
1654 if (ndev_vif->ap.non_ht_bss_present) {
1655 u8 op_mode = 1;
1656
1657 SLSI_NET_DBG1(ndev_vif->wdev.netdev, SLSI_MLME, "Modify Operating mode of BSS in HT IE\n");
1658 slsi_modify_ies(ndev_vif->wdev.netdev, WLAN_EID_HT_OPERATION, (u8 *)settings->beacon.tail, settings->beacon.tail_len, 4, op_mode);
1659 ndev_vif->ap.non_ht_bss_present = false;
1660 }
1661
1662 /* Vendor IEs are excluded from start_req. Currently WPA IE, WMM IE, WPS IE and P2P IE need to be excluded.
1663 * From hostapd, order of IEs are - WPA, WMM, WPS and P2P
1664 * Of these the WMM, WPS and P2P IE are usually at the end.
1665 * Note: There can be "eid_p2p_manage" and "eid_hs20" after WPS and P2P IE. Both of these are currently not supported.
1666 */
1667
1668 /* Exclude WMM or WPS IE */
1669 if (wmm_ie_pos) /* WMM IE is present. Remove from this position onwards, i.e. copy only till this data. WPS and P2P IE will also get removed. */
1670 beacon_ie_len = wmm_ie_pos - beacon_tail;
1671 else {
1672 /* WMM IE is not present. Check for WPS IE (and thereby P2P IE) and exclude it */
1673 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, beacon_tail, beacon_tail_len);
1674 if (wps_ie)
1675 beacon_ie_len = wps_ie - beacon_tail;
1676 else
1677 beacon_ie_len = beacon_tail_len;
1678 }
1679
1680 /* Exclude WPA IE if present */
1681 if (wpa_ie_pos) {
1682 size_t len_before, len;
1683
1684 len_before = wpa_ie_pos - beacon_tail;
1685 fapi_append_data(req, beacon_tail, len_before);
1686
1687 len = len_before + ndev_vif->ap.wpa_ie_len;
1688
1689 if (beacon_ie_len > len) { /* More IEs to go */
1690 tail_length = beacon_ie_len - len;
1691 tail_pos = (beacon_tail + len);
1692 } else /* No more IEs, don't add Ext Capab IE as no HT/VHT */
1693 return;
1694 } else {
1695 tail_length = beacon_ie_len;
1696 tail_pos = beacon_tail;
1697 }
1698
1699 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1700 /* Add Ext Capab IE only for VHT mode for now */
1701 if (ndev_vif->chandef->width == NL80211_CHAN_WIDTH_80) {
1702 /* Ext Capab should be before VHT IEs */
1703 vht_capab_ie = (cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, tail_pos, tail_length));
1704 ext_capab_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, tail_pos, tail_length);
1705 while (tail_length > 2) {
1706 if (tail_pos[0] == WLAN_EID_VHT_CAPABILITY)
1707 slsi_ap_add_ext_capab_ie(req, ndev_vif, ext_capab_ie);
1708 else if (tail_pos[0] != WLAN_EID_EXT_CAPABILITY && tail_pos[0] != WLAN_EID_VHT_OPERATION)
1709 fapi_append_data(req, tail_pos, tail_pos[1] + 2);
1710
1711 tail_length -= tail_pos[1] + 2;
1712 tail_pos += tail_pos[1] + 2;
1713 }
1714 if (!vht_capab_ie)
1715 slsi_ap_add_ext_capab_ie(req, ndev_vif, ext_capab_ie);
1716 } else {
1717 fapi_append_data(req, tail_pos, tail_length);
1718 }
1719 #else
1720 fapi_append_data(req, tail_pos, tail_length);
1721 #endif
1722 }
1723
1724 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1725 /*EID + LEN + CAPABILITIES + MCS */
1726 /* 1+1+4+8 */
1727 #define SLSI_VHT_CAPABILITIES_IE_LEN 14
1728
1729 /* EID + LEN + WIDTH + SEG0 + SEG1 + MCS */
1730 /* 1+1+1+1+1+2 */
1731 #define SLSI_VHT_OPERATION_IE_LEN 7
1732
1733 static int slsi_prepare_vht_ies(struct net_device *dev, u8 **vht_ie_capab, u8 **vht_ie_operation)
1734 {
1735 u32 capabs;
1736 u16 mcs;
1737 u8 *p_cap, *p_oper;
1738 struct netdev_vif *ndev_vif = netdev_priv(dev);
1739
1740 *vht_ie_capab = kmalloc(SLSI_VHT_CAPABILITIES_IE_LEN, GFP_KERNEL);
1741 if (!(*vht_ie_capab))
1742 return -EINVAL;
1743 *vht_ie_operation = kmalloc(SLSI_VHT_OPERATION_IE_LEN, GFP_KERNEL);
1744 if (!(*vht_ie_operation)) {
1745 kfree(*vht_ie_capab);
1746 return -EINVAL;
1747 }
1748
1749 p_cap = *vht_ie_capab;
1750 p_oper = *vht_ie_operation;
1751
1752 *p_cap++ = WLAN_EID_VHT_CAPABILITY;
1753 *p_cap++ = SLSI_VHT_CAPABILITIES_IE_LEN - 1 - 1;
1754 capabs = cpu_to_le32(slsi_vht_cap.cap);
1755 memcpy(p_cap, &capabs, sizeof(capabs));
1756 p_cap += sizeof(capabs);
1757 memcpy(p_cap, &slsi_vht_cap.vht_mcs, sizeof(slsi_vht_cap.vht_mcs));
1758
1759 *p_oper++ = WLAN_EID_VHT_OPERATION;
1760 *p_oper++ = SLSI_VHT_OPERATION_IE_LEN - 1 - 1;
1761 *p_oper++ = IEEE80211_VHT_CHANWIDTH_80MHZ;
1762 *p_oper++ = ieee80211_frequency_to_channel(ndev_vif->chandef->center_freq1);
1763 *p_oper++ = 0;
1764 mcs = cpu_to_le16(0xfffc);
1765 memcpy(p_oper, &mcs, sizeof(mcs));
1766
1767 return 0;
1768 }
1769 #endif
1770
1771 int slsi_mlme_start(struct slsi_dev *sdev, struct net_device *dev, u8 *bssid, struct cfg80211_ap_settings *settings, const u8 *wpa_ie_pos, const u8 *wmm_ie_pos, bool append_vht_ies)
1772 {
1773 struct netdev_vif *ndev_vif = netdev_priv(dev);
1774 struct sk_buff *req;
1775 struct sk_buff *cfm;
1776 struct ieee80211_mgmt *mgmt;
1777 int r = 0;
1778 u8 *p;
1779 enum nl80211_auth_type auth_type = settings->auth_type;
1780 u16 beacon_ie_head_len;
1781 u16 chan_info;
1782 u16 fw_freq;
1783 u16 vht_ies_len = 0;
1784 u8 ext_capab_len = 0;
1785 const u8 *recv_vht_capab_ie, *recv_vht_operation_ie;
1786
1787 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1788 u8 *vht_ie_capab, *vht_ie_operation;
1789 #endif
1790 SLSI_UNUSED_PARAMETER(bssid);
1791
1792 if (slsi_is_test_mode_enabled()) {
1793 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_START.request\n");
1794 return -EOPNOTSUPP;
1795 }
1796
1797 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
1798
1799 mgmt = (struct ieee80211_mgmt *)settings->beacon.head;
1800 beacon_ie_head_len = settings->beacon.head_len - ((u8 *)mgmt->u.beacon.variable - (u8 *)mgmt);
1801
1802 /* For port enabling, save the privacy bit used in assoc response or beacon */
1803 ndev_vif->ap.privacy = (mgmt->u.beacon.capab_info & WLAN_CAPABILITY_PRIVACY);
1804 ndev_vif->ap.qos_enabled = (mgmt->u.beacon.capab_info & WLAN_CAPABILITY_QOS);
1805
1806 switch (auth_type) {
1807 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1808 case NL80211_AUTHTYPE_SHARED_KEY:
1809 break;
1810 case NL80211_AUTHTYPE_AUTOMATIC:
1811 auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
1812 if (settings->privacy && settings->crypto.cipher_group == 0)
1813 auth_type = NL80211_AUTHTYPE_SHARED_KEY;
1814 break;
1815 default:
1816 SLSI_NET_ERR(dev, "Unsupported auth_type: %d\n", auth_type);
1817 return -EOPNOTSUPP;
1818 }
1819
1820 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_start_req(vif:%u, bssid:%pM, ssid:%.*s, hidden:%d)\n", ndev_vif->ifnum, bssid, (int)settings->ssid_len, settings->ssid, settings->hidden_ssid);
1821
1822 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1823 if (append_vht_ies)
1824 vht_ies_len = SLSI_VHT_CAPABILITIES_IE_LEN + SLSI_VHT_OPERATION_IE_LEN;
1825
1826 recv_vht_capab_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, settings->beacon.tail,
1827 settings->beacon.tail_len);
1828 if (recv_vht_capab_ie)
1829 vht_ies_len -= (recv_vht_capab_ie[1] + 2);
1830
1831 recv_vht_operation_ie = cfg80211_find_ie(WLAN_EID_VHT_OPERATION, settings->beacon.tail,
1832 settings->beacon.tail_len);
1833 if (recv_vht_operation_ie)
1834 vht_ies_len -= (recv_vht_operation_ie[1] + 2);
1835
1836 if (ndev_vif->chandef->width == NL80211_CHAN_WIDTH_80) {
1837 /* Ext Capab are not advertised by driver and so the IE would not be sent by hostapd.
1838 * Frame the IE in driver and set the required bit(s).
1839 */
1840 SLSI_NET_DBG1(dev, SLSI_MLME, "VHT - Ext Capab IE to be included\n");
1841 ext_capab_len = SLSI_AP_EXT_CAPAB_IE_LEN_MAX;
1842 }
1843 #endif
1844
1845 if (settings->hidden_ssid == 1)
1846 req = fapi_alloc(mlme_start_req, MLME_START_REQ, ndev_vif->ifnum, settings->ssid_len + beacon_ie_head_len + settings->beacon.tail_len + vht_ies_len + ext_capab_len);
1847 else
1848 req = fapi_alloc(mlme_start_req, MLME_START_REQ, ndev_vif->ifnum, beacon_ie_head_len + settings->beacon.tail_len + vht_ies_len + ext_capab_len);
1849
1850 if (!req)
1851 return -ENOMEM;
1852 fapi_set_memcpy(req, u.mlme_start_req.bssid, dev->dev_addr);
1853 fapi_set_u16(req, u.mlme_start_req.beacon_period, settings->beacon_interval);
1854 fapi_set_u16(req, u.mlme_start_req.dtim_period, settings->dtim_period);
1855 fapi_set_u16(req, u.mlme_start_req.capability_information, le16_to_cpu(mgmt->u.beacon.capab_info));
1856 fapi_set_u16(req, u.mlme_start_req.authentication_type, auth_type);
1857 fapi_set_u16(req, u.mlme_start_req.hidden_ssid, settings->hidden_ssid < 3 ? settings->hidden_ssid : NL80211_HIDDEN_SSID_ZERO_LEN);
1858
1859 fw_freq = ndev_vif->chan->center_freq;
1860 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1861 chan_info = slsi_get_chann_info(sdev, ndev_vif->chandef);
1862 #else
1863 chan_info = slsi_get_chann_info(sdev, ndev_vif->channel_type);
1864 #endif
1865 if ((chan_info & 20) != 20)
1866 fw_freq = slsi_get_center_freq1(sdev, chan_info, fw_freq);
1867
1868 fapi_set_u16(req, u.mlme_start_req.channel_frequency, (2 * fw_freq));
1869 fapi_set_u16(req, u.mlme_start_req.channel_information, chan_info);
1870 ndev_vif->ap.channel_freq = fw_freq;
1871
1872 /* Addition of SSID IE in mlme_start_req for hiddenSSID case */
1873 if (settings->hidden_ssid != 0) {
1874 p = fapi_append_data(req, NULL, 2 + settings->ssid_len);
1875 if (!p) {
1876 slsi_kfree_skb(req);
1877 return -EINVAL;
1878 }
1879 *p++ = WLAN_EID_SSID;
1880 *p++ = settings->ssid_len;
1881 memcpy(p, settings->ssid, settings->ssid_len);
1882 }
1883
1884 if (beacon_ie_head_len && settings->hidden_ssid == 0)
1885 fapi_append_data(req, mgmt->u.beacon.variable, beacon_ie_head_len);
1886 else if (beacon_ie_head_len && settings->hidden_ssid == 1)
1887 fapi_append_data(req, mgmt->u.beacon.variable + 2, beacon_ie_head_len - 2);
1888 else if (beacon_ie_head_len && settings->hidden_ssid == 2)
1889 fapi_append_data(req, mgmt->u.beacon.variable + 2 + settings->ssid_len, beacon_ie_head_len - (2 + settings->ssid_len));
1890
1891 if (settings->beacon.tail_len)
1892 slsi_mlme_start_prepare_ies(req, ndev_vif, settings, wpa_ie_pos, wmm_ie_pos);
1893
1894 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1895 if ((append_vht_ies) && !slsi_prepare_vht_ies(dev, &vht_ie_capab, &vht_ie_operation)) {
1896 fapi_append_data(req, vht_ie_capab, SLSI_VHT_CAPABILITIES_IE_LEN);
1897 fapi_append_data(req, vht_ie_operation, SLSI_VHT_OPERATION_IE_LEN);
1898 kfree(vht_ie_capab);
1899 kfree(vht_ie_operation);
1900 }
1901 #endif
1902
1903 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_START_CFM);
1904 if (!cfm)
1905 return -EIO;
1906 if (fapi_get_u16(cfm, u.mlme_start_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
1907 SLSI_NET_ERR(dev, "mlme_start_cfm(result:0x%04x) ERROR\n",
1908 fapi_get_u16(cfm, u.mlme_start_cfm.result_code));
1909 r = -EINVAL;
1910 }
1911
1912 slsi_kfree_skb(cfm);
1913 return r;
1914 }
1915
1916 static const u8 *slsi_mlme_connect_get_sec_ie(struct cfg80211_connect_params *sme, int *sec_ie_len)
1917 {
1918 u16 version;
1919 const u8 *ptr = NULL;
1920
1921 if (sme->crypto.wpa_versions == 0) {
1922 /* WAPI */
1923 ptr = cfg80211_find_ie(SLSI_WLAN_EID_WAPI, sme->ie, sme->ie_len);
1924 if (ptr) {
1925 version = ptr[3] << 8 | ptr[2];
1926 if (version != 1) {
1927 SLSI_ERR_NODEV("Unexpected version (%d) in WAPI ie\n", version);
1928 return NULL;
1929 }
1930 }
1931 } else if (sme->crypto.wpa_versions == 2) {
1932 /* RSN */
1933 ptr = cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len);
1934
1935 if (ptr) {
1936 /* version index is 2 for RSN */
1937 version = ptr[2 + 1] << 8 | ptr[2];
1938 if (version != 1) {
1939 SLSI_ERR_NODEV("Unexpected version (%d) in rsn ie\n", version);
1940 return NULL;
1941 }
1942 }
1943 }
1944 *sec_ie_len = ptr ? ptr[1] + 2 : 0;
1945 return ptr;
1946 }
1947
1948 /* If is_copy is true copy the required IEs from connect_ie to ie_dest. else
1949 * calculate the required ie length
1950 */
1951 static int slsi_mlme_connect_info_elems_ie_prep(struct slsi_dev *sdev, const u8 *connect_ie,
1952 const size_t connect_ie_len, bool is_copy, u8 *ie_dest, int ie_dest_len)
1953 {
1954 const u8 *ie_pos = NULL;
1955 int info_elem_length = 0;
1956 u16 curr_ie_len;
1957 int i = 0;
1958 u8 ie_eid[] = {SLSI_WLAN_EID_INTERWORKING,
1959 SLSI_WLAN_EID_EXTENSION,
1960 WLAN_EID_VENDOR_SPECIFIC}; /*Vendor IE has to be the last element */
1961
1962 if (is_copy && (!ie_dest || ie_dest_len == 0))
1963 return -EINVAL;
1964
1965 for (i = 0; i < sizeof(ie_eid) / sizeof(u8); i++) {
1966 ie_pos = cfg80211_find_ie(ie_eid[i], connect_ie, connect_ie_len);
1967 if (ie_pos) {
1968 if (ie_eid[i] == WLAN_EID_VENDOR_SPECIFIC) /*Vendor IE will be the last element */
1969 curr_ie_len = connect_ie_len - (ie_pos - connect_ie);
1970 else
1971 curr_ie_len = *(ie_pos + 1) + 2;
1972 SLSI_DBG2(sdev, SLSI_MLME, "IE[%d] is present having length:%d\n", ie_eid[i], curr_ie_len);
1973 if (is_copy) {
1974 if (ie_dest_len >= curr_ie_len) {
1975 memcpy(ie_dest, ie_pos, curr_ie_len);
1976 ie_dest += curr_ie_len;
1977 /* free space avail in ie_dest for next ie*/
1978 ie_dest_len -= curr_ie_len;
1979 } else {
1980 SLSI_ERR_NODEV("IE[%d] extract error (ie_copy_l:%d, c_ie_l:%d):\n", ie_eid[i],
1981 ie_dest_len, curr_ie_len);
1982 return -EINVAL;
1983 }
1984 } else {
1985 info_elem_length += curr_ie_len;
1986 }
1987 }
1988 }
1989
1990 if (sdev->device_config.qos_info != -1) {
1991 if (is_copy) {
1992 if (ie_dest_len >= 9) {
1993 int pos = 0;
1994
1995 ie_dest[pos++] = SLSI_WLAN_EID_VENDOR_SPECIFIC;
1996 ie_dest[pos++] = 0x07;
1997 ie_dest[pos++] = 0x00;
1998 ie_dest[pos++] = 0x50;
1999 ie_dest[pos++] = 0xf2;
2000 ie_dest[pos++] = WLAN_OUI_TYPE_MICROSOFT_WMM;
2001 ie_dest[pos++] = WMM_OUI_SUBTYPE_INFORMATION_ELEMENT;
2002 ie_dest[pos++] = WMM_VERSION;
2003 ie_dest[pos++] = sdev->device_config.qos_info & 0x0F;
2004 ie_dest += pos;
2005 ie_dest_len -= pos;
2006 } else {
2007 SLSI_ERR_NODEV("Required 9bytes but left:%d\n", ie_dest_len);
2008 return -EINVAL;
2009 }
2010 } else {
2011 info_elem_length += 9;
2012 }
2013 }
2014 return info_elem_length;
2015 }
2016
2017 static int slsi_mlme_connect_info_elements(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_connect_params *sme)
2018 {
2019 struct netdev_vif *ndev_vif = netdev_priv(dev);
2020 int info_elem_length = 0;
2021 struct sk_buff *req;
2022 struct sk_buff *cfm;
2023 int r = 0;
2024 u8 *p;
2025
2026 info_elem_length = slsi_mlme_connect_info_elems_ie_prep(sdev, sme->ie, sme->ie_len, false, NULL, 0);
2027
2028 /* NO IE required in MLME-ADD-INFO-ELEMENTS */
2029 if (info_elem_length <= 0)
2030 return info_elem_length;
2031
2032 req = fapi_alloc(mlme_add_info_elements_req, MLME_ADD_INFO_ELEMENTS_REQ,
2033 ndev_vif->ifnum, info_elem_length);
2034 if (!req)
2035 return -ENOMEM;
2036
2037 fapi_set_u16(req, u.mlme_add_info_elements_req.purpose, FAPI_PURPOSE_ASSOCIATION_REQUEST);
2038
2039 p = fapi_append_data(req, NULL, info_elem_length);
2040 if (!p) {
2041 slsi_kfree_skb(req);
2042 return -EINVAL;
2043 }
2044
2045 (void)slsi_mlme_connect_info_elems_ie_prep(sdev, sme->ie, sme->ie_len, true, p, info_elem_length);
2046
2047 /* backup ies */
2048 if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) {
2049 if (ndev_vif->sta.assoc_req_add_info_elem_len)
2050 kfree(ndev_vif->sta.assoc_req_add_info_elem);
2051 ndev_vif->sta.assoc_req_add_info_elem_len = 0;
2052
2053 ndev_vif->sta.assoc_req_add_info_elem = kmalloc(info_elem_length, GFP_KERNEL);
2054 if (ndev_vif->sta.assoc_req_add_info_elem) {
2055 memcpy(ndev_vif->sta.assoc_req_add_info_elem, p, info_elem_length);
2056 ndev_vif->sta.assoc_req_add_info_elem_len = info_elem_length;
2057 } else {
2058 SLSI_WARN(sdev, "No mem for ndev_vif->sta.assoc_req_add_info_elem size %d\n", info_elem_length);
2059 }
2060 }
2061
2062 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_add_info_elements_req(vif:%u)\n", ndev_vif->ifnum);
2063 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_ADD_INFO_ELEMENTS_CFM);
2064 if (!cfm)
2065 return -EIO;
2066
2067 if (fapi_get_u16(cfm, u.mlme_add_info_elements_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
2068 SLSI_NET_ERR(dev, "mlme_add_info_elements_cfm(result:0x%04x) ERROR\n",
2069 fapi_get_u16(cfm, u.mlme_connect_cfm.result_code));
2070 r = -EINVAL;
2071 }
2072
2073 if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, sme->ie, sme->ie_len))
2074 ndev_vif->sta.is_wps = true;
2075
2076 slsi_kfree_skb(cfm);
2077 return r;
2078 }
2079
2080 int slsi_mlme_connect(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_connect_params *sme, struct ieee80211_channel *channel, const u8 *bssid)
2081 {
2082 struct netdev_vif *ndev_vif = netdev_priv(dev);
2083 struct sk_buff *req;
2084 struct sk_buff *cfm;
2085 int r = 0;
2086 u8 *p;
2087 enum nl80211_auth_type auth_type = sme->auth_type;
2088 u8 mac_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2089 struct key_params slsi_key;
2090 const u8 *sec_ie = NULL;
2091 int sec_ie_len = 0;
2092
2093 memset(&slsi_key, 0, sizeof(slsi_key));
2094
2095 if (slsi_is_test_mode_enabled()) {
2096 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_CONNECT.request\n");
2097 return -EOPNOTSUPP;
2098 }
2099
2100 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
2101
2102 if (WARN(!bssid, "BSSID is Null"))
2103 return -EINVAL;
2104
2105 if (WARN(!sme->ssid_len, "SSID is Null"))
2106 return -EINVAL;
2107
2108 switch (auth_type) {
2109 case NL80211_AUTHTYPE_OPEN_SYSTEM:
2110 case NL80211_AUTHTYPE_SHARED_KEY:
2111 break;
2112 case NL80211_AUTHTYPE_SAE:
2113 auth_type = NL80211_AUTHTYPE_NETWORK_EAP;
2114 break;
2115 case NL80211_AUTHTYPE_AUTOMATIC:
2116 /* In case of WEP, need to try both open and shared.
2117 * FW does this if auth is shared_key. So set it to shared.
2118 */
2119 if (sme->privacy &&
2120 (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40 ||
2121 sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104))
2122 auth_type = NL80211_AUTHTYPE_SHARED_KEY;
2123 else
2124 auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
2125 break;
2126 default:
2127 SLSI_NET_ERR(dev, "Unsupported auth_type: %d\n", auth_type);
2128 return -EOPNOTSUPP;
2129 }
2130
2131 /* We save the WEP key for shared authentication. */
2132 if ((auth_type == NL80211_AUTHTYPE_SHARED_KEY) &&
2133 ((sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) ||
2134 (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104)) &&
2135 (ndev_vif->vif_type == FAPI_VIFTYPE_STATION)) {
2136 SLSI_NET_DBG3(dev, SLSI_MLME, "key len (%d)\n", sme->key_len);
2137 slsi_key.key = (u8 *)sme->key;
2138 if (!slsi_key.key)
2139 return -EINVAL;
2140 slsi_key.key_len = sme->key_len;
2141 slsi_key.seq_len = 0;
2142 if (sme->crypto.n_ciphers_pairwise)
2143 slsi_key.cipher = sme->crypto.ciphers_pairwise[0];
2144
2145 r = slsi_mlme_set_key(sdev, dev, sme->key_idx, FAPI_KEYTYPE_WEP, mac_addr, &slsi_key);
2146 if (r != 0) {
2147 SLSI_NET_ERR(dev, "Error Setting Shared key (%d)", r);
2148 return r;
2149 }
2150 }
2151
2152 /*Do not check sme->ie as wpa_supplicant sends some invalid value in it even if ie_len is zero .*/
2153 if (sme->ie_len) {
2154 r = slsi_mlme_connect_info_elements(sdev, dev, sme);
2155 if (r)
2156 return r;
2157
2158 sec_ie = slsi_mlme_connect_get_sec_ie(sme, &sec_ie_len);
2159 if (sec_ie_len < 0) {
2160 SLSI_NET_ERR(dev, "ERROR preparing Security IEs\n");
2161 return sec_ie_len;
2162 }
2163 }
2164
2165 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_connect_req(vif:%u, bssid:%pM, ssid:%.*s)\n", ndev_vif->ifnum, bssid, (int)sme->ssid_len, sme->ssid);
2166 req = fapi_alloc(mlme_connect_req, MLME_CONNECT_REQ, ndev_vif->ifnum,
2167 2 + sme->ssid_len + /*SSID IE*/
2168 sec_ie_len); /*WPA/WPA2/WAPI/OSEN*/
2169 if (!req)
2170 return -ENOMEM;
2171
2172 fapi_set_memcpy(req, u.mlme_connect_req.bssid, bssid);
2173 fapi_set_u16(req, u.mlme_connect_req.authentication_type, auth_type);
2174 /* Need to double the freq for the firmware */
2175 fapi_set_u16(req, u.mlme_connect_req.channel_frequency, (2 * channel->center_freq));
2176
2177 p = fapi_append_data(req, NULL, 2 + sme->ssid_len + sec_ie_len);
2178 if (!p) {
2179 slsi_kfree_skb(req);
2180 return -EINVAL;
2181 }
2182 *p++ = WLAN_EID_SSID;
2183 *p++ = sme->ssid_len;
2184 memcpy(p, sme->ssid, sme->ssid_len);
2185 p += sme->ssid_len;
2186
2187 if (sec_ie_len)
2188 memcpy(p, sec_ie, sec_ie_len);
2189 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_CONNECT_CFM);
2190 if (!cfm)
2191 return -EIO;
2192
2193 if (fapi_get_u16(cfm, u.mlme_connect_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
2194 SLSI_NET_ERR(dev, "mlme_connect_cfm(result:0x%04x) ERROR\n",
2195 fapi_get_u16(cfm, u.mlme_connect_cfm.result_code));
2196 r = -EINVAL;
2197 }
2198
2199 slsi_kfree_skb(cfm);
2200 return r;
2201 }
2202
2203 void slsi_mlme_connect_resp(struct slsi_dev *sdev, struct net_device *dev)
2204 {
2205 struct netdev_vif *ndev_vif = netdev_priv(dev);
2206 struct sk_buff *req;
2207 struct sk_buff *cfm;
2208
2209 if (slsi_is_test_mode_enabled()) {
2210 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_CONNECT_RESP\n");
2211 return;
2212 }
2213
2214 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_connect_resp(vif:%u)\n", ndev_vif->ifnum);
2215 req = fapi_alloc(mlme_connect_res, MLME_CONNECT_RES, ndev_vif->ifnum, 0);
2216 if (!req)
2217 return;
2218
2219 cfm = slsi_mlme_req_no_cfm(sdev, dev, req);
2220 WARN_ON(cfm);
2221 }
2222
2223 void slsi_mlme_connected_resp(struct slsi_dev *sdev, struct net_device *dev, u16 peer_index)
2224 {
2225 struct netdev_vif *ndev_vif = netdev_priv(dev);
2226 struct sk_buff *req;
2227
2228 if (slsi_is_test_mode_enabled()) {
2229 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_CONNECT_RESP\n");
2230 return;
2231 }
2232
2233 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_connected_resp(vif:%u, peer_index:%d)\n", ndev_vif->ifnum, peer_index);
2234 req = fapi_alloc(mlme_connected_res, MLME_CONNECTED_RES, ndev_vif->ifnum, 0);
2235 if (!req) {
2236 SLSI_NET_ERR(dev, "mlme-connected-response :: memory allocation failed\n");
2237 return;
2238 }
2239
2240 fapi_set_u16(req, u.mlme_connected_res.association_identifier, peer_index);
2241 slsi_mlme_req_no_cfm(sdev, dev, req);
2242 }
2243
2244 void slsi_mlme_roamed_resp(struct slsi_dev *sdev, struct net_device *dev)
2245 {
2246 struct netdev_vif *ndev_vif = netdev_priv(dev);
2247 struct sk_buff *req;
2248 struct sk_buff *cfm;
2249
2250 if (slsi_is_test_mode_enabled()) {
2251 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_ROAMED_RESP\n");
2252 return;
2253 }
2254
2255 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_roamed_resp\n");
2256 req = fapi_alloc(mlme_roamed_res, MLME_ROAMED_RES, ndev_vif->ifnum, 0);
2257 if (!req)
2258 return;
2259
2260 cfm = slsi_mlme_req_no_cfm(sdev, dev, req);
2261 WARN_ON(cfm);
2262 }
2263
2264 /* Null check for cfm done in caller function */
2265 bool slsi_disconnect_cfm_validate(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm)
2266 {
2267 int result = fapi_get_u16(cfm, u.mlme_disconnect_cfm.result_code);
2268 bool r = false;
2269
2270 SLSI_UNUSED_PARAMETER(sdev);
2271
2272 if (WARN_ON(!dev))
2273 goto exit;
2274
2275 if (result == FAPI_RESULTCODE_SUCCESS)
2276 r = true;
2277 /* Not present code would mean peer is already disconnected and hence no ind (could be race scenario), don't log as error */
2278 else if (result != FAPI_RESULTCODE_NOT_PRESENT)
2279 SLSI_NET_ERR(dev, "mlme_disconnect_cfm(result:0x%04x) ERROR\n",
2280 fapi_get_u16(cfm, u.mlme_disconnect_cfm.result_code));
2281
2282 exit:
2283 slsi_kfree_skb(cfm);
2284 return r;
2285 }
2286
2287 int slsi_mlme_disconnect(struct slsi_dev *sdev, struct net_device *dev, u8 *mac, u16 reason_code, bool wait_ind)
2288 {
2289 struct netdev_vif *ndev_vif = netdev_priv(dev);
2290 struct sk_buff *req;
2291 struct sk_buff *rx;
2292 int r = 0;
2293
2294 if (slsi_is_test_mode_enabled()) {
2295 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_DISCONNECT.request\n");
2296 return -EOPNOTSUPP;
2297 }
2298
2299 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
2300
2301 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_disconnect_req(vif:%u, bssid:%pM, reason:%d)\n", ndev_vif->ifnum, mac, reason_code);
2302
2303 req = fapi_alloc(mlme_disconnect_req, MLME_DISCONNECT_REQ, ndev_vif->ifnum,
2304 ndev_vif->sta.vendor_disconnect_ies_len);
2305
2306 if (!req)
2307 return -ENOMEM;
2308 SLSI_INFO(sdev, "Send DEAUTH, reason = %d\n", reason_code);
2309 fapi_set_u16(req, u.mlme_disconnect_req.reason_code, reason_code);
2310 if (ndev_vif->sta.vendor_disconnect_ies_len > 0)
2311 fapi_append_data(req, ndev_vif->sta.vendor_disconnect_ies, ndev_vif->sta.vendor_disconnect_ies_len);
2312 kfree(ndev_vif->sta.vendor_disconnect_ies);
2313 ndev_vif->sta.vendor_disconnect_ies = NULL;
2314 ndev_vif->sta.vendor_disconnect_ies_len = 0;
2315
2316 if (mac)
2317 fapi_set_memcpy(req, u.mlme_disconnect_req.peer_sta_address, mac);
2318 else
2319 fapi_set_memset(req, u.mlme_disconnect_req.peer_sta_address, 0);
2320 if (wait_ind) {
2321 rx = slsi_mlme_req_cfm_ind(sdev, dev, req, MLME_DISCONNECT_CFM, MLME_DISCONNECT_IND, slsi_disconnect_cfm_validate);
2322 if (!rx) {
2323 SLSI_NET_ERR(dev, "mlme_disconnect_cfm() ERROR\n");
2324 r = -EINVAL;
2325 }
2326 } else {
2327 rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_DISCONNECT_CFM);
2328 if (rx) {
2329 if (fapi_get_u16(rx, u.mlme_disconnect_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
2330 SLSI_NET_ERR(dev, "mlme_disconnect_cfm(result:0x%04x) ERROR\n",
2331 fapi_get_u16(rx, u.mlme_disconnect_cfm.result_code));
2332 r = -EINVAL;
2333 }
2334 } else {
2335 r = -EIO;
2336 }
2337 }
2338
2339 slsi_kfree_skb(rx);
2340 return r;
2341 }
2342
2343 int slsi_mlme_set_key(struct slsi_dev *sdev, struct net_device *dev, u16 key_id, u16 key_type, const u8 *address, struct key_params *key)
2344 {
2345 struct netdev_vif *ndev_vif = netdev_priv(dev);
2346 struct sk_buff *req;
2347 struct sk_buff *cfm;
2348 int r = 0;
2349
2350 if (slsi_is_test_mode_enabled()) {
2351 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_SETKEYS.request\n");
2352 return -EOPNOTSUPP;
2353 }
2354
2355 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
2356
2357 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_setkeys_req(key_id:%d, key_type:%d, address:%pM, length:%d, cipher:0x%.8X)\n", key_id, key_type, address, key->key_len, key->cipher);
2358 req = fapi_alloc(mlme_setkeys_req, MLME_SETKEYS_REQ, ndev_vif->ifnum, key->key_len + 1); /* + 1 for the wep key index */
2359 if (!req)
2360 return -ENOMEM;
2361 fapi_set_u16(req, u.mlme_setkeys_req.length, key->key_len * 8);
2362 fapi_set_u16(req, u.mlme_setkeys_req.key_id, key_id);
2363 fapi_set_u16(req, u.mlme_setkeys_req.key_type, key_type);
2364 fapi_set_memcpy(req, u.mlme_setkeys_req.address, address);
2365 fapi_set_memset(req, u.mlme_setkeys_req.sequence_number, 0x00);
2366
2367 if (key->seq_len && key->seq) {
2368 int i;
2369 u16 temp_seq;
2370
2371 SLSI_NET_DBG3(dev, SLSI_MLME, "mlme_setkeys_req(key->seq_len:%d)\n", key->seq_len);
2372
2373 /* Sequence would be in little endian format
2374 * If sequence is say key->seq is
2375 * 04 03 02 01 00 00 00 00, it would be encoded as :
2376 * 0x0304 0x0102 0x0000 0x0000 for firmware
2377 */
2378 for (i = 0; i < key->seq_len; i += 2) {
2379 temp_seq = (u16)(key->seq[i + 1] << 8) | (u16)(key->seq[i]);
2380 fapi_set_u16(req, u.mlme_setkeys_req.sequence_number[i / 2], temp_seq);
2381 }
2382 }
2383
2384 fapi_set_u32(req, u.mlme_setkeys_req.cipher_suite_selector, key->cipher);
2385
2386 if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) {
2387 u8 wep_key_id = (u8)key_id;
2388
2389 if (key_id > 3)
2390 SLSI_NET_WARN(dev, "Key ID is greater than 3");
2391 /* Incase of WEP key index is appended before key.
2392 * So increment length by one
2393 */
2394 fapi_set_u16(req, u.mlme_setkeys_req.length, (key->key_len + 1) * 8);
2395 fapi_append_data(req, &wep_key_id, 1);
2396 }
2397 fapi_append_data(req, key->key, key->key_len);
2398
2399 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SETKEYS_CFM);
2400 if (!cfm)
2401 return -EIO;
2402
2403 if (fapi_get_u16(cfm, u.mlme_setkeys_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
2404 SLSI_NET_ERR(dev, "mlme_setkeys_cfm(result:0x%04x) ERROR\n",
2405 fapi_get_u16(cfm, u.mlme_setkeys_cfm.result_code));
2406 r = -EINVAL;
2407 }
2408 slsi_kfree_skb(cfm);
2409 return r;
2410 }
2411
2412 int slsi_mlme_get_key(struct slsi_dev *sdev, struct net_device *dev, u16 key_id, u16 key_type, u8 *seq, int *seq_len)
2413 {
2414 struct netdev_vif *ndev_vif = netdev_priv(dev);
2415 struct sk_buff *req;
2416 struct sk_buff *cfm;
2417 int r = 0;
2418
2419 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
2420
2421 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_get_key_sequence_req(key_id:%d, key_type:%d)\n", key_id, key_type);
2422 req = fapi_alloc(mlme_get_key_sequence_req, MLME_GET_KEY_SEQUENCE_REQ, ndev_vif->ifnum, 0);
2423 if (!req)
2424 return -ENOMEM;
2425 fapi_set_u16(req, u.mlme_get_key_sequence_req.key_id, key_id);
2426 fapi_set_u16(req, u.mlme_get_key_sequence_req.key_type, key_type);
2427
2428 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_GET_KEY_SEQUENCE_CFM);
2429 if (!cfm)
2430 return -EIO;
2431
2432 if (fapi_get_u16(cfm, u.mlme_get_key_sequence_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
2433 SLSI_NET_ERR(dev, "mlme_get_key_sequence_cfm(result:0x%04x) ERROR\n",
2434 fapi_get_u16(cfm, u.mlme_get_key_sequence_cfm.result_code));
2435 r = -ENOENT;
2436 } else {
2437 int i;
2438 u16 temp_seq;
2439
2440 /* For WPA2 Key RSC - 8 octets. For WPAI, it would be 16 octets (code would need to be updated)
2441 * Length is not available in cfm but even if max length 8 is assigned, it should be ok as other octets
2442 * would be padded with 0s
2443 */
2444 *seq_len = 8;
2445
2446 /* Sequence from firmware is of a[8] type u16 (16 octets) and only 8 octets are required for WPA/WPA2.
2447 * If sequence is say 0x01 0x02 0x03 0x04 with 0x01 as MSB and 0x04 as LSB then
2448 * it would be encoded as: 0x0304 0x0102 by firmware.
2449 * Sequence is expected to be returned in little endian
2450 */
2451
2452 for (i = 0; i < *seq_len / 2; i++) {
2453 temp_seq = fapi_get_u16(cfm, u.mlme_get_key_sequence_cfm.sequence_number[i]);
2454 *seq = (u8)(temp_seq & 0xFF);
2455 *(seq + 1) = (u8)((temp_seq >> 8) & 0xFF);
2456
2457 seq += 2;
2458 }
2459 }
2460
2461 slsi_kfree_skb(cfm);
2462 return r;
2463 }
2464
2465 void slsi_calc_max_data_rate(struct net_device *dev, u8 bandwidth, u8 antenna_mode)
2466 {
2467 struct netdev_vif *ndev_vif = netdev_priv(dev);
2468 u8 bandwidth_index, sta_mode, mcs_index;
2469
2470 if (bandwidth == 0 || antenna_mode > 3) {
2471 SLSI_NET_ERR(dev, "MIB value is wrong.");
2472 return;
2473 }
2474
2475 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
2476
2477 /* Bandwidth (BW): 0x0= 20 MHz, 0x1= 40 MHz, 0x2= 80 MHz, 0x3= 160/ 80+80 MHz. 0x3 is not supported */
2478 bandwidth_index = bandwidth / 40;
2479 sta_mode = slsi_sta_ieee80211_mode(dev, ndev_vif->sta.sta_bss->channel->center_freq);
2480
2481 if (sta_mode == SLSI_80211_MODE_11B) {
2482 ndev_vif->sta.max_rate_mbps = 11;
2483 } else if (sta_mode == SLSI_80211_MODE_11G || sta_mode == SLSI_80211_MODE_11A) {
2484 ndev_vif->sta.max_rate_mbps = 54;
2485 } else if (sta_mode == SLSI_80211_MODE_11N) { /* max mcs index = 7 */
2486 ndev_vif->sta.max_rate_mbps = (unsigned long)(slsi_rates_table[bandwidth_index][1][7] * (antenna_mode + 1)) / 10;
2487 } else if (sta_mode == SLSI_80211_MODE_11AC) {
2488 if (bandwidth_index == 0)
2489 mcs_index = 8;
2490 else
2491 mcs_index = 9;
2492 ndev_vif->sta.max_rate_mbps = (unsigned long)(slsi_rates_table[bandwidth_index][1][mcs_index] * (antenna_mode + 1)) / 10;
2493 }
2494 }
2495
2496 void slsi_decode_fw_rate(u16 fw_rate, struct rate_info *rate, unsigned long *data_rate_mbps)
2497 {
2498 const int fw_rate_idx_to_80211_rate[] = { 0, 10, 20, 55, 60, 90, 110, 120, 180, 240, 360, 480, 540 };
2499
2500 if (rate) {
2501 rate->flags = 0;
2502 rate->legacy = 0;
2503 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2504 rate->bw = 0;
2505 #endif
2506 }
2507
2508 if ((fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) == SLSI_FW_API_RATE_NON_HT_SELECTED) {
2509 u16 fw_rate_idx = fw_rate & SLSI_FW_API_RATE_INDEX_FIELD;
2510
2511 if (fw_rate > 0 && fw_rate_idx < ARRAY_SIZE(fw_rate_idx_to_80211_rate)) {
2512 if (rate)
2513 rate->legacy = fw_rate_idx_to_80211_rate[fw_rate_idx];
2514 if (data_rate_mbps)
2515 *data_rate_mbps = fw_rate_idx_to_80211_rate[fw_rate_idx] / 10;
2516 }
2517 } else if ((fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) == SLSI_FW_API_RATE_HT_SELECTED) {
2518 u8 mcs_idx = SLSI_FW_API_RATE_HT_MCS_FIELD & fw_rate;
2519 u8 nss = ((SLSI_FW_API_RATE_HT_NSS_FIELD & fw_rate) >> 6) + 1;
2520
2521 if (rate) {
2522 rate->flags |= RATE_INFO_FLAGS_MCS;
2523 rate->mcs = mcs_idx;
2524
2525 if ((fw_rate & SLSI_FW_API_RATE_BW_FIELD) == SLSI_FW_API_RATE_BW_40MHZ)
2526 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2527 rate->bw |= RATE_INFO_BW_40;
2528 #else
2529 rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
2530 #endif
2531 if (fw_rate & SLSI_FW_API_RATE_SGI)
2532 rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
2533 }
2534
2535 if (data_rate_mbps) {
2536 int chan_bw_idx;
2537 int gi_idx;
2538
2539 chan_bw_idx = (fw_rate & SLSI_FW_API_RATE_BW_FIELD) >> 9;
2540 gi_idx = ((fw_rate & SLSI_FW_API_RATE_SGI) == SLSI_FW_API_RATE_SGI) ? 1 : 0;
2541
2542 /* nss will be 1 when mcs_idx <= 7 or mcs == 32 */
2543 if (chan_bw_idx < 2) {
2544 if (mcs_idx <= 7) {
2545 *data_rate_mbps = slsi_rates_table[chan_bw_idx][gi_idx][mcs_idx] / 10;
2546 } else if (mcs_idx <= 15) {
2547 *data_rate_mbps = (unsigned long)(nss * slsi_rates_table[chan_bw_idx][gi_idx][mcs_idx - 8]) / 10;
2548 } else if (mcs_idx == 32 && chan_bw_idx == 1) {
2549 /* TODO: Fix this : unsigned long will not hold decimal values */
2550 if (gi_idx == 1)
2551 *data_rate_mbps = (unsigned long) 6.7;
2552 else
2553 *data_rate_mbps = 6;
2554 }
2555 } else {
2556 SLSI_WARN_NODEV("FW DATA RATE decode error fw_rate:%x, bw:%x, mcs_idx:%x, nss : %d\n",
2557 fw_rate, chan_bw_idx, mcs_idx, nss);
2558 }
2559 }
2560 } else if ((fw_rate & SLSI_FW_API_RATE_HT_SELECTOR_FIELD) == SLSI_FW_API_RATE_VHT_SELECTED) {
2561 int chan_bw_idx;
2562 int gi_idx;
2563 int mcs_idx;
2564 u8 nss;
2565
2566 /* report vht rate in legacy units and not as mcs index. reason: upper layers may still be not
2567 * updated with vht msc table.
2568 */
2569 chan_bw_idx = (fw_rate & SLSI_FW_API_RATE_BW_FIELD) >> 9;
2570 gi_idx = ((fw_rate & SLSI_FW_API_RATE_SGI) == SLSI_FW_API_RATE_SGI) ? 1 : 0;
2571 /* Calculate NSS --> bits 6 to 4*/
2572 nss = ((SLSI_FW_API_RATE_VHT_NSS_FIELD & fw_rate) >> 4) + 1;
2573 mcs_idx = SLSI_FW_API_RATE_VHT_MCS_FIELD & fw_rate;
2574 /* Bandwidth (BW): 0x0= 20 MHz, 0x1= 40 MHz, 0x2= 80 MHz, 0x3= 160/ 80+80 MHz. 0x3 is not supported */
2575 if ((chan_bw_idx <= 2) && (mcs_idx <= 9)) {
2576 if (rate)
2577 rate->legacy = nss * slsi_rates_table[chan_bw_idx][gi_idx][mcs_idx];
2578 if (data_rate_mbps)
2579 *data_rate_mbps = (unsigned long)(nss * slsi_rates_table[chan_bw_idx][gi_idx][mcs_idx]) / 10;
2580 } else {
2581 SLSI_WARN_NODEV("FW DATA RATE decode error fw_rate:%x, bw:%x, mcs_idx:%x,nss : %d\n", fw_rate, chan_bw_idx, mcs_idx, nss);
2582 }
2583 }
2584 }
2585
2586 int slsi_mlme_get_sinfo_mib(struct slsi_dev *sdev, struct net_device *dev,
2587 struct slsi_peer *peer)
2588 {
2589 struct netdev_vif *ndev_vif = netdev_priv(dev);
2590 struct slsi_mib_data mibreq = { 0, NULL };
2591 struct slsi_mib_data mibrsp = { 0, NULL };
2592 struct slsi_mib_value *values = NULL;
2593 u8 bandwidth = 0, antenna_mode = 4;
2594 int data_length = 0;
2595 int r = 0;
2596 int mib_index = 0;
2597 static const struct slsi_mib_get_entry get_values[] = {
2598 { SLSI_PSID_UNIFI_TX_DATA_RATE, { 0, 0 } }, /* to get STATION_INFO_TX_BITRATE*/
2599 { SLSI_PSID_UNIFI_RX_DATA_RATE, { 0, 0 } }, /* to get STATION_INFO_RX_BITRATE*/
2600 { SLSI_PSID_UNIFI_RSSI, { 0, 0 } }, /* to get STATION_INFO_SIGNAL_AVG*/
2601 { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 3, 0 } }, /* bad_fcs_count*/
2602 { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 25, 0 } }, /* mac_bad_sig_count*/
2603 { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG, { 30, 0 } }, /* rx_error_count*/
2604 { SLSI_PSID_UNIFI_FRAME_TX_COUNTERS, { 1, 0 } }, /*tx good count*/
2605 { SLSI_PSID_UNIFI_FRAME_TX_COUNTERS, { 2, 0 } }, /*tx bad count*/
2606 { SLSI_PSID_UNIFI_FRAME_RX_COUNTERS, { 1, 0 } }, /*rx good count*/
2607 { SLSI_PSID_UNIFI_CURRENT_BSS_BANDWIDTH, { 0, 0 } }, /* bss bandwidth */
2608 #ifdef CONFIG_SCSC_ENHANCED_PACKET_STATS
2609 { SLSI_PSID_UNIFI_FRAME_TX_COUNTERS, { 3, 0 } }, /*tx retry count*/
2610 #endif
2611 { SLSI_PSID_UNIFI_STA_VIF_LINK_NSS, { 0, 0 } } /* current nss */
2612 };
2613 int rx_counter = 0;
2614
2615 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
2616
2617 if (!peer) {
2618 SLSI_WARN(sdev, "Peer Not available\n");
2619 return -EINVAL;
2620 }
2621
2622 /*check if function is called within given period*/
2623 if (__ratelimit(&peer->sinfo_mib_get_rs))
2624 return 0;
2625
2626 r = slsi_mib_encode_get_list(&mibreq, (sizeof(get_values) / sizeof(struct slsi_mib_get_entry)),
2627 get_values);
2628 if (r != SLSI_MIB_STATUS_SUCCESS)
2629 return -ENOMEM;
2630
2631 /* Fixed fields len (5) : 2 bytes(PSID) + 2 bytes (Len) + 1 byte (VLDATA header ) [10 for 2 PSIDs]
2632 * Data : 3*2 bytes for SLSI_PSID_UNIFI_TX_DATA_RATE & SLSI_PSID_UNIFI_RX_DATA_RATE, 1 byte for SLSI_PSID_UNIFI_RSSI
2633 * 10*7 bytes for 3 Throughput Mib's and 4 counter Mib's
2634 */
2635 mibrsp.dataLength = 114;
2636 mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL);
2637
2638 if (!mibrsp.data) {
2639 SLSI_NET_DBG1(dev, SLSI_MLME, "failed to allocate memory\n");
2640 kfree(mibreq.data);
2641 return -ENOMEM;
2642 }
2643
2644 r = slsi_mlme_get(sdev, dev, mibreq.data, mibreq.dataLength, mibrsp.data,
2645 mibrsp.dataLength, &data_length);
2646 kfree(mibreq.data);
2647
2648 if (r == 0) {
2649 mibrsp.dataLength = (u32)data_length;
2650 values = slsi_mib_decode_get_list(&mibrsp,
2651 (sizeof(get_values) / sizeof(struct slsi_mib_get_entry)), get_values);
2652 if (!values) {
2653 SLSI_NET_DBG1(dev, SLSI_MLME, "mib decode list failed\n");
2654 kfree(mibrsp.data);
2655 return -ENOMEM;
2656 }
2657
2658 if (values[mib_index].type != SLSI_MIB_TYPE_NONE) {
2659 SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_UINT);
2660 slsi_decode_fw_rate((u16)values[mib_index].u.uintValue, &peer->sinfo.txrate, &ndev_vif->sta.data_rate_mbps);
2661 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2662 peer->sinfo.filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
2663 #else
2664 peer->sinfo.filled |= STATION_INFO_TX_BITRATE;
2665 #endif
2666 SLSI_DBG3(sdev, SLSI_MLME, "SLSI_PSID_UNIFI_TX_DATA_RATE = 0x%x\n",
2667 values[mib_index].u.uintValue);
2668 }
2669 else
2670 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2671
2672 if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) {
2673 SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_UINT);
2674 slsi_decode_fw_rate((u16)values[mib_index].u.uintValue, &peer->sinfo.rxrate, NULL);
2675 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2676 peer->sinfo.filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
2677 #else
2678 peer->sinfo.filled |= STATION_INFO_RX_BITRATE;
2679 #endif
2680 SLSI_DBG3(sdev, SLSI_MLME, "SLSI_PSID_UNIFI_RX_DATA_RATE = 0x%x\n",
2681 values[mib_index].u.uintValue);
2682 }
2683 else
2684 SLSI_DBG3(sdev, SLSI_MLME, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2685
2686 if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) {
2687 SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_INT);
2688 if (values[mib_index].u.intValue >= 0)
2689 peer->sinfo.signal = -1;
2690 else
2691 peer->sinfo.signal = (s8)values[mib_index].u.intValue;
2692 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2693 peer->sinfo.filled |= BIT(NL80211_STA_INFO_SIGNAL);
2694 #else
2695 peer->sinfo.filled |= STATION_INFO_SIGNAL;
2696 #endif
2697 SLSI_DBG3(sdev, SLSI_MLME, "SLSI_PSID_UNIFI_RSSI = %d\n",
2698 values[mib_index].u.intValue);
2699 }
2700 else
2701 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2702
2703 if (values[++mib_index].type == SLSI_MIB_TYPE_UINT)
2704 rx_counter += values[mib_index].u.uintValue; /*bad_fcs_count*/
2705 else
2706 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2707 if (values[++mib_index].type == SLSI_MIB_TYPE_UINT)
2708 rx_counter += values[mib_index].u.uintValue; /*mac_bad_sig_count*/
2709 else
2710 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2711 if (values[++mib_index].type == SLSI_MIB_TYPE_UINT)
2712 rx_counter += values[mib_index].u.uintValue; /*rx_error_count*/
2713 else
2714 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2715 if (values[++mib_index].type == SLSI_MIB_TYPE_UINT)
2716 peer->sinfo.tx_packets = values[mib_index].u.uintValue; /*tx good count*/
2717 else
2718 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2719 if (values[++mib_index].type == SLSI_MIB_TYPE_UINT)
2720 peer->sinfo.tx_failed = values[mib_index].u.uintValue; /*tx bad count*/
2721 else
2722 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2723 if (values[++mib_index].type == SLSI_MIB_TYPE_UINT)
2724 peer->sinfo.rx_packets = values[mib_index].u.uintValue; /*rx good count*/
2725 else
2726 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2727 if (values[++mib_index].type == SLSI_MIB_TYPE_UINT)
2728 bandwidth = values[mib_index].u.uintValue; /* bss bandwidth */
2729 else
2730 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2731 #ifdef CONFIG_SCSC_ENHANCED_PACKET_STATS
2732 if (values[++mib_index].type == SLSI_MIB_TYPE_UINT)
2733 peer->sinfo.tx_retries = values[mib_index].u.uintValue; /*tx retry count*/
2734 else
2735 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2736 #endif
2737 if (values[++mib_index].type == SLSI_MIB_TYPE_UINT) {
2738 antenna_mode = values[mib_index].u.uintValue; /* current nss */
2739 slsi_calc_max_data_rate(dev, bandwidth, antenna_mode);
2740 } else {
2741 SLSI_ERR(sdev, "Invalid type: PSID = 0x%x\n", get_values[mib_index].psid);
2742 }
2743
2744 peer->sinfo.rx_dropped_misc = rx_counter;
2745
2746 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2747 peer->sinfo.filled |= BIT(NL80211_STA_INFO_TX_FAILED) | BIT(NL80211_STA_INFO_RX_DROP_MISC) |
2748 BIT(NL80211_STA_INFO_TX_PACKETS) | BIT(NL80211_STA_INFO_RX_PACKETS);
2749 #ifdef CONFIG_SCSC_ENHANCED_PACKET_STATS
2750 peer->sinfo.filled |= BIT(NL80211_STA_INFO_TX_RETRIES);
2751 #endif
2752 #endif
2753 } else {
2754 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_get_req failed(result:0x%4x)\n", r);
2755 }
2756
2757 kfree(mibrsp.data);
2758 kfree(values);
2759 return r;
2760 }
2761
2762 int slsi_mlme_connect_scan(struct slsi_dev *sdev, struct net_device *dev,
2763 u32 n_ssids, struct cfg80211_ssid *ssids, struct ieee80211_channel *channel)
2764 {
2765 struct netdev_vif *ndev_vif = netdev_priv(dev);
2766 int r = 0;
2767 struct ieee80211_channel **scan_channels = NULL;
2768 struct ieee80211_channel **add_scan_channels;
2769 int n_channels = 0;
2770 struct sk_buff *scan;
2771 struct cfg80211_scan_info info = {.aborted = true};
2772
2773 SLSI_MUTEX_LOCK(ndev_vif->scan_mutex);
2774
2775 if (ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req) {
2776 SLSI_NET_DBG3(dev, SLSI_MLME, "stop on-going Scan\n");
2777 (void)slsi_mlme_del_scan(sdev, dev, ndev_vif->ifnum << 8 | SLSI_SCAN_HW_ID, false);
2778 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
2779 cfg80211_scan_done(ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req, &info);
2780 #else
2781 cfg80211_scan_done(ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req, true);
2782 #endif
2783
2784 ndev_vif->scan[SLSI_SCAN_HW_ID].scan_req = NULL;
2785 }
2786
2787 if (!channel) {
2788 enum nl80211_band band;
2789 struct wiphy *wiphy = sdev->wiphy;
2790 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
2791 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2792 #else
2793 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2794 #endif
2795 if (!wiphy->bands[band])
2796 continue;
2797 n_channels += wiphy->bands[band]->n_channels;
2798 }
2799
2800 WARN_ON(n_channels == 0);
2801 scan_channels = kmalloc_array((size_t)n_channels, sizeof(*scan_channels), GFP_KERNEL);
2802 if (!scan_channels) {
2803 SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex);
2804 return -ENOMEM;
2805 }
2806 n_channels = 0;
2807 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
2808 for (band = 0; band < NUM_NL80211_BANDS; band++) {
2809 #else
2810 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2811 #endif
2812 int j;
2813
2814 if (!wiphy->bands[band])
2815 continue;
2816 for (j = 0; j < wiphy->bands[band]->n_channels; j++)
2817 if (!(wiphy->bands[band]->channels[j].flags & IEEE80211_CHAN_DISABLED)) {
2818 scan_channels[n_channels] = &wiphy->bands[band]->channels[j];
2819 n_channels++;
2820 }
2821 }
2822 add_scan_channels = scan_channels;
2823 } else {
2824 n_channels = 1;
2825 add_scan_channels = &channel;
2826 }
2827 ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = true;
2828 r = slsi_mlme_add_scan(sdev,
2829 dev,
2830 FAPI_SCANTYPE_FULL_SCAN,
2831 FAPI_REPORTMODE_REAL_TIME,
2832 n_ssids,
2833 ssids,
2834 n_channels,
2835 add_scan_channels,
2836 NULL,
2837 ndev_vif->probe_req_ies,
2838 ndev_vif->probe_req_ie_len,
2839 ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan);
2840
2841 SLSI_MUTEX_LOCK(ndev_vif->scan_result_mutex);
2842 scan = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL);
2843 while (scan) {
2844 slsi_rx_scan_pass_to_cfg80211(sdev, dev, scan);
2845 scan = slsi_dequeue_cached_scan_result(&ndev_vif->scan[SLSI_SCAN_HW_ID], NULL);
2846 }
2847 SLSI_MUTEX_UNLOCK(ndev_vif->scan_result_mutex);
2848
2849 kfree(scan_channels);
2850 ndev_vif->scan[SLSI_SCAN_HW_ID].is_blocking_scan = false;
2851
2852 SLSI_MUTEX_UNLOCK(ndev_vif->scan_mutex);
2853 return r;
2854 }
2855
2856 /**
2857 * The powermgt_lock mutex is to ensure atomic update of the power management state.
2858 */
2859 DEFINE_MUTEX(powermgt_lock);
2860 /**
2861 * The slsi_mlme_powermgt_unlocked() must be called from a context that is synchronised
2862 * with ndev_vif. if called without the ndev_vif mutex already taken, other mechanisms
2863 * must ensure that ndev_vif will exist for the duration of the function.
2864 */
2865 int slsi_mlme_powermgt_unlocked(struct slsi_dev *sdev, struct net_device *dev, u16 power_mode)
2866 {
2867 struct netdev_vif *ndev_vif = netdev_priv(dev);
2868 struct sk_buff *req;
2869 struct sk_buff *rx;
2870 int r = 0;
2871
2872 mutex_lock(&powermgt_lock);
2873
2874 if (WARN_ON(!ndev_vif->activated)) {
2875 mutex_unlock(&powermgt_lock);
2876 return -EINVAL;
2877 }
2878
2879 if (ndev_vif->power_mode == power_mode) {
2880 mutex_unlock(&powermgt_lock);
2881 SLSI_NET_DBG3(dev, SLSI_MLME, "power management mode is same as requested. No changes done\n");
2882 return 0;
2883 }
2884
2885 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_powermgt_req(vif:%d, power_management_mode:%d)\n", ndev_vif->ifnum, power_mode);
2886 req = fapi_alloc(mlme_powermgt_req, MLME_POWERMGT_REQ, ndev_vif->ifnum, 0);
2887 if (!req) {
2888 mutex_unlock(&powermgt_lock);
2889 return -ENOMEM;
2890 }
2891 fapi_set_u16(req, u.mlme_powermgt_req.power_management_mode, power_mode);
2892
2893 rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_POWERMGT_CFM);
2894 if (!rx) {
2895 mutex_unlock(&powermgt_lock);
2896 return -EIO;
2897 }
2898
2899 if (fapi_get_u16(rx, u.mlme_powermgt_cfm.result_code) == FAPI_RESULTCODE_SUCCESS) {
2900 ndev_vif->power_mode = power_mode;
2901 } else {
2902 SLSI_NET_ERR(dev, "mlme_powermgt_cfm(result:0x%04x) ERROR\n",
2903 fapi_get_u16(rx, u.mlme_powermgt_cfm.result_code));
2904 r = -EINVAL;
2905 }
2906
2907 slsi_kfree_skb(rx);
2908 mutex_unlock(&powermgt_lock);
2909 return r;
2910 }
2911
2912 int slsi_mlme_powermgt(struct slsi_dev *sdev, struct net_device *dev, u16 power_mode)
2913 {
2914 struct netdev_vif *ndev_vif = netdev_priv(dev);
2915
2916 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
2917
2918 return slsi_mlme_powermgt_unlocked(sdev, dev, power_mode);
2919 }
2920
2921 #ifdef CONFIG_SCSC_WLAN_SAE_CONFIG
2922 int slsi_mlme_synchronised_response(struct slsi_dev *sdev, struct net_device *dev,
2923 struct cfg80211_external_auth_params *params)
2924 {
2925 struct netdev_vif *ndev_vif = netdev_priv(dev);
2926 struct sk_buff *req;
2927 struct sk_buff *cfm;
2928 if (ndev_vif->activated) {
2929 SLSI_NET_DBG3(dev, SLSI_MLME, "MLME_SYNCHRONISED_RES\n");
2930
2931 req = fapi_alloc(mlme_synchronised_res, MLME_SYNCHRONISED_RES, ndev_vif->ifnum, 0);
2932 if (!req)
2933 return -ENOMEM;
2934
2935 fapi_set_u16(req, u.mlme_synchronised_res.result_code, params->status);
2936 fapi_set_memcpy(req, u.mlme_synchronised_res.bssid, params->bssid);
2937
2938 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_synchronised_response(vif:%d) status:%d\n",
2939 ndev_vif->ifnum, params->status);
2940 cfm = slsi_mlme_req_no_cfm(sdev, dev, req);
2941 if (cfm)
2942 SLSI_NET_ERR(dev, "Received cfm for MLME_SYNCHRONISED_RES\n");
2943 } else
2944 SLSI_NET_DBG1(dev, SLSI_MLME, "vif is not active");
2945
2946 return 0;
2947 }
2948 #endif
2949
2950 int slsi_mlme_register_action_frame(struct slsi_dev *sdev, struct net_device *dev, u32 af_bitmap_active, u32 af_bitmap_suspended)
2951 {
2952 struct netdev_vif *ndev_vif = netdev_priv(dev);
2953 struct sk_buff *req;
2954 struct sk_buff *cfm;
2955 int r = 0;
2956
2957 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
2958
2959 req = fapi_alloc(mlme_register_action_frame_req, MLME_REGISTER_ACTION_FRAME_REQ, ndev_vif->ifnum, 0);
2960 if (!req)
2961 return -ENOMEM;
2962
2963 fapi_set_u32(req, u.mlme_register_action_frame_req.action_frame_category_bitmap_active, af_bitmap_active);
2964 fapi_set_u32(req, u.mlme_register_action_frame_req.action_frame_category_bitmap_suspended, af_bitmap_suspended);
2965
2966 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_register_action_frame(vif:%d, active:%d, suspended:%d)\n", ndev_vif->ifnum, af_bitmap_active, af_bitmap_suspended);
2967 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_REGISTER_ACTION_FRAME_CFM);
2968 if (!cfm)
2969 return -EIO;
2970
2971 if (fapi_get_u16(cfm, u.mlme_register_action_frame_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
2972 SLSI_NET_ERR(dev, "mlme_register_action_frame_cfm(result:0x%04x) ERROR\n",
2973 fapi_get_u16(cfm, u.mlme_register_action_frame_cfm.result_code));
2974 r = -EINVAL;
2975 }
2976
2977 slsi_kfree_skb(cfm);
2978 return r;
2979 }
2980
2981 int slsi_mlme_channel_switch(struct slsi_dev *sdev, struct net_device *dev, u16 center_freq, u16 chan_info)
2982 {
2983 struct netdev_vif *ndev_vif = netdev_priv(dev);
2984 struct sk_buff *req;
2985 struct sk_buff *cfm;
2986 int r = 0;
2987
2988 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
2989
2990 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_channel_switch_req(vif:%d, freq: %d, channel info: 0x%x)\n", ndev_vif->ifnum, center_freq, chan_info);
2991 req = fapi_alloc(mlme_channel_switch_req, MLME_CHANNEL_SWITCH_REQ, ndev_vif->ifnum, 0);
2992 if (!req)
2993 return -ENOMEM;
2994
2995 fapi_set_u16(req, u.mlme_channel_switch_req.channel_frequency, SLSI_FREQ_HOST_TO_FW(center_freq));
2996 fapi_set_u16(req, u.mlme_channel_switch_req.channel_information, chan_info);
2997
2998 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_CHANNEL_SWITCH_CFM);
2999 if (!cfm)
3000 return -EIO;
3001
3002 if (fapi_get_u16(cfm, u.mlme_channel_switch_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3003 SLSI_NET_ERR(dev, "mlme_channel_switch_cfm(result:0x%04x) ERROR\n",
3004 fapi_get_u16(cfm, u.mlme_channel_switch_cfm.result_code));
3005 r = -EINVAL;
3006 }
3007
3008 slsi_kfree_skb(cfm);
3009 return r;
3010 }
3011
3012 int slsi_mlme_add_info_elements(struct slsi_dev *sdev, struct net_device *dev, u16 purpose, const u8 *ies, const u16 ies_len)
3013 {
3014 struct netdev_vif *ndev_vif = netdev_priv(dev);
3015 struct sk_buff *req;
3016 struct sk_buff *cfm;
3017 int r = 0;
3018 u8 *p;
3019
3020 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
3021
3022 req = fapi_alloc(mlme_add_info_elements_req, MLME_ADD_INFO_ELEMENTS_REQ, ndev_vif->ifnum, ies_len);
3023 if (!req)
3024 return -ENOMEM;
3025
3026 fapi_set_u16(req, u.mlme_add_info_elements_req.purpose, purpose);
3027
3028 if (ies_len != 0) {
3029 p = fapi_append_data(req, ies, ies_len);
3030 if (!p) {
3031 slsi_kfree_skb(req);
3032 return -EINVAL;
3033 }
3034 }
3035
3036 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_add_info_elements_req(vif:%d, ies_len:%d)\n", ndev_vif->ifnum, ies_len);
3037 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_ADD_INFO_ELEMENTS_CFM);
3038 if (!cfm)
3039 return -EIO;
3040
3041 if (fapi_get_u16(cfm, u.mlme_add_info_elements_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3042 SLSI_NET_ERR(dev, "mlme_add_info_elements_cfm(result:0x%04x) ERROR\n",
3043 fapi_get_u16(cfm, u.mlme_add_info_elements_cfm.result_code));
3044 r = -EINVAL;
3045 }
3046
3047 slsi_kfree_skb(cfm);
3048 return r;
3049 }
3050
3051 int slsi_mlme_send_frame_data(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 msg_type,
3052 u16 host_tag, u32 dwell_time, u32 period)
3053 {
3054 struct netdev_vif *ndev_vif = netdev_priv(dev);
3055 u16 len = skb->len;
3056 struct sk_buff *original_skb = 0;
3057 int ret;
3058 #ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
3059 int is_enhanced_arp_request_frame = 0;
3060 #endif
3061
3062 /* don't let ARP frames exhaust all the control slots */
3063 if (msg_type == FAPI_MESSAGETYPE_ARP) {
3064 int free_slots = 0;
3065
3066 free_slots = hip4_free_ctrl_slots_count(&sdev->hip4_inst);
3067
3068 if (free_slots < 0) {
3069 SLSI_DBG1(sdev, SLSI_MLME, "drop ARP (error in getting free slot count)\n");
3070 return free_slots;
3071 }
3072
3073 if (free_slots < SLSI_MLME_ARP_DROP_FREE_SLOTS_COUNT) {
3074 SLSI_DBG1(sdev, SLSI_MLME, "drop ARP (running out of Control slots:%d)\n", free_slots);
3075 slsi_kfree_skb(skb);
3076 return NETDEV_TX_OK;
3077 }
3078
3079 #ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
3080 if (ndev_vif->enhanced_arp_detect_enabled && (msg_type == FAPI_MESSAGETYPE_ARP)) {
3081 u8 *frame = skb->data + sizeof(struct ethhdr);
3082 u16 arp_opcode = frame[SLSI_ARP_OPCODE_OFFSET] << 8 | frame[SLSI_ARP_OPCODE_OFFSET + 1];
3083
3084 if ((arp_opcode == SLSI_ARP_REQUEST_OPCODE) &&
3085 !SLSI_IS_GRATUITOUS_ARP(frame) &&
3086 !memcmp(&frame[SLSI_ARP_DEST_IP_ADDR_OFFSET], &ndev_vif->target_ip_addr, 4))
3087 is_enhanced_arp_request_frame = 1;
3088 }
3089 #endif
3090 }
3091
3092 /* check for headroom to push signal header; if not available, re-alloc headroom */
3093 if (skb_headroom(skb) < (fapi_sig_size(mlme_send_frame_req))) {
3094 struct sk_buff *skb2 = NULL;
3095
3096 skb2 = slsi_skb_realloc_headroom(skb, fapi_sig_size(mlme_send_frame_req));
3097 if (!skb2)
3098 return -EINVAL;
3099 original_skb = skb;
3100 skb = skb2;
3101 }
3102 len = skb->len;
3103 (void)skb_push(skb, (fapi_sig_size(mlme_send_frame_req)));
3104
3105 /* fill the signal header */
3106 fapi_set_u16(skb, id, MLME_SEND_FRAME_REQ);
3107 fapi_set_u16(skb, receiver_pid, 0);
3108 fapi_set_u16(skb, sender_pid, SLSI_TX_PROCESS_ID_MIN);
3109 fapi_set_u16(skb, fw_reference, 0);
3110
3111 /* fill in signal parameters */
3112 fapi_set_u16(skb, u.mlme_send_frame_req.vif, ndev_vif->ifnum);
3113
3114 if (host_tag == 0)
3115 host_tag = slsi_tx_mgmt_host_tag(sdev);
3116
3117 fapi_set_u16(skb, u.mlme_send_frame_req.host_tag, host_tag);
3118 fapi_set_u16(skb, u.mlme_send_frame_req.data_unit_descriptor, FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME);
3119 fapi_set_u16(skb, u.mlme_send_frame_req.message_type, msg_type);
3120 fapi_set_u16(skb, u.mlme_send_frame_req.channel_frequency, 0);
3121 fapi_set_u32(skb, u.mlme_send_frame_req.dwell_time, dwell_time);
3122 fapi_set_u32(skb, u.mlme_send_frame_req.period, period);
3123
3124 SLSI_DBG2(sdev, SLSI_MLME, "mlme_send_frame_req(vif:%d, message_type:%d, host_tag:%d)\n", ndev_vif->ifnum, msg_type, host_tag);
3125 /* slsi_tx_control frees the skb. Do not use it after this call. */
3126 ret = slsi_tx_control(sdev, dev, skb);
3127 if (ret != 0) {
3128 SLSI_WARN(sdev, "failed to send MLME signal(err=%d)\n", ret);
3129 return ret;
3130 }
3131
3132 #ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
3133 if (is_enhanced_arp_request_frame) {
3134 int i;
3135
3136 ndev_vif->enhanced_arp_stats.arp_req_count_to_lower_mac++;
3137 for (i = 0; i < SLSI_MAX_ARP_SEND_FRAME; i++) {
3138 if (!ndev_vif->enhanced_arp_host_tag[i]) {
3139 ndev_vif->enhanced_arp_host_tag[i] = host_tag;
3140 break;
3141 }
3142 }
3143 }
3144 #endif
3145
3146 if (original_skb)
3147 slsi_kfree_skb(original_skb);
3148
3149 /* as the frame is queued to HIP for transmission, store the host tag of the frames
3150 * to validate the transmission status in MLME-Frame-Transmission.indication.
3151 * Take necessary action based on the type of frame and status of it's transmission
3152 */
3153 if (msg_type == FAPI_MESSAGETYPE_EAPOL_KEY_M4) {
3154 ndev_vif->sta.m4_host_tag = host_tag;
3155 SLSI_NET_DBG1(dev, SLSI_MLME, "EAPOL-Key M4 frame (host_tag:%d)\n", ndev_vif->sta.m4_host_tag);
3156 } else if (msg_type == FAPI_MESSAGETYPE_EAP_MESSAGE) {
3157 if (!ndev_vif->sta.is_wps && (ndev_vif->iftype == NL80211_IFTYPE_STATION)) {
3158 /* In case of non-P2P station and Enterprise security store the host_tag.
3159 * If transmission of such frame fails, inform supplicant to disconnect.
3160 */
3161 ndev_vif->sta.eap_hosttag = host_tag;
3162 SLSI_NET_DBG1(dev, SLSI_MLME, "EAP frame (host_tag:%d)\n", ndev_vif->sta.eap_hosttag);
3163 }
3164 }
3165 return ret;
3166 }
3167
3168 int slsi_mlme_send_frame_mgmt(struct slsi_dev *sdev, struct net_device *dev, const u8 *frame, int frame_len,
3169 u16 data_desc, u16 msg_type, u16 host_tag, u16 freq, u32 dwell_time, u32 period)
3170 {
3171 struct netdev_vif *ndev_vif = netdev_priv(dev);
3172 struct sk_buff *req;
3173 struct sk_buff *cfm;
3174 int r = 0;
3175 u8 *p;
3176
3177 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
3178
3179 req = fapi_alloc(mlme_send_frame_req, MLME_SEND_FRAME_REQ, ndev_vif->ifnum, frame_len);
3180 if (!req) {
3181 SLSI_WARN(sdev, "failed to alloc memory\n");
3182 return -ENOMEM;
3183 }
3184
3185 fapi_set_u16(req, u.mlme_send_frame_req.host_tag, host_tag);
3186 fapi_set_u16(req, u.mlme_send_frame_req.data_unit_descriptor, data_desc);
3187 fapi_set_u16(req, u.mlme_send_frame_req.message_type, msg_type);
3188 fapi_set_u16(req, u.mlme_send_frame_req.channel_frequency, freq);
3189 fapi_set_u32(req, u.mlme_send_frame_req.dwell_time, dwell_time);
3190 fapi_set_u32(req, u.mlme_send_frame_req.period, period);
3191
3192 p = fapi_append_data(req, frame, frame_len);
3193 if (!p) {
3194 slsi_kfree_skb(req);
3195 SLSI_WARN(sdev, "failed to append data\n");
3196 return -EINVAL;
3197 }
3198
3199 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_send_frame_req(vif:%d, message_type:%d,host_tag:%d)\n", ndev_vif->ifnum, msg_type, host_tag);
3200 slsi_debug_frame(sdev, dev, req, "TX");
3201 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SEND_FRAME_CFM);
3202 if (!cfm)
3203 return -EIO;
3204
3205 if (fapi_get_u16(cfm, u.mlme_send_frame_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3206 SLSI_NET_ERR(dev, "mlme_send_frame_cfm(result:0x%04x) ERROR\n",
3207 fapi_get_u16(cfm, u.mlme_send_frame_cfm.result_code));
3208 r = -EINVAL;
3209 }
3210
3211 slsi_kfree_skb(cfm);
3212 return r;
3213 }
3214
3215 int slsi_mlme_reset_dwell_time(struct slsi_dev *sdev, struct net_device *dev)
3216 {
3217 struct netdev_vif *ndev_vif = netdev_priv(dev);
3218 struct sk_buff *req;
3219 struct sk_buff *cfm;
3220 int r = 0;
3221
3222 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
3223
3224 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_reset_dwell_time_req (vif:%d)\n", ndev_vif->ifnum);
3225
3226 req = fapi_alloc(mlme_reset_dwell_time_req, MLME_RESET_DWELL_TIME_REQ, ndev_vif->ifnum, 0);
3227
3228 if (!req)
3229 return -ENOMEM;
3230
3231 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_RESET_DWELL_TIME_CFM);
3232 if (!cfm)
3233 return -EIO;
3234
3235 if (fapi_get_u16(cfm, u.mlme_reset_dwell_time_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3236 SLSI_NET_ERR(dev, "mlme_reset_dwell_time_cfm(result:0x%04x) ERROR\n",
3237 fapi_get_u16(cfm, u.mlme_reset_dwell_time_cfm.result_code));
3238 r = -EINVAL;
3239 }
3240
3241 slsi_kfree_skb(cfm);
3242 return r;
3243 }
3244
3245 int slsi_mlme_set_packet_filter(struct slsi_dev *sdev, struct net_device *dev,
3246 int pkt_filter_len,
3247 u8 num_filters,
3248 struct slsi_mlme_pkt_filter_elem *pkt_filter_elems)
3249 {
3250 struct netdev_vif *ndev_vif = netdev_priv(dev);
3251 struct sk_buff *req;
3252 struct sk_buff *cfm;
3253 int r = 0, i = 0, j = 0;
3254 u8 *p;
3255 u8 index = 0;
3256
3257 if (WARN_ON(!ndev_vif->activated))
3258 return -EINVAL;
3259
3260 if (WARN_ON(!num_filters))
3261 return -EINVAL;
3262
3263 req = fapi_alloc(mlme_set_packet_filter_req, MLME_SET_PACKET_FILTER_REQ, ndev_vif->ifnum, pkt_filter_len);
3264 if (!req)
3265 return -ENOMEM;
3266
3267 p = fapi_append_data(req, NULL, pkt_filter_len);
3268 if (!p) {
3269 slsi_kfree_skb(req);
3270 return -EINVAL;
3271 }
3272
3273 for (i = 0; i < num_filters; i++) {
3274 struct slsi_mlme_pkt_filter_elem pkt_filter_elem = pkt_filter_elems[i];
3275
3276 memcpy(&p[index], pkt_filter_elem.header, SLSI_PKT_FILTER_ELEM_HDR_LEN);
3277 index += SLSI_PKT_FILTER_ELEM_HDR_LEN;
3278
3279 for (j = 0; j < pkt_filter_elem.num_pattern_desc; j++) {
3280 p[index++] = pkt_filter_elem.pattern_desc[j].offset;
3281 p[index++] = pkt_filter_elem.pattern_desc[j].mask_length;
3282 memcpy(&p[index], pkt_filter_elem.pattern_desc[j].mask, pkt_filter_elem.pattern_desc[j].mask_length);
3283 index += pkt_filter_elem.pattern_desc[j].mask_length;
3284 memcpy(&p[index], pkt_filter_elem.pattern_desc[j].pattern, pkt_filter_elem.pattern_desc[j].mask_length);
3285 index += pkt_filter_elem.pattern_desc[j].mask_length;
3286 }
3287 }
3288
3289 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_packet_filter_req(vif:%d, num_filters:%d)\n", ndev_vif->ifnum, num_filters);
3290 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_PACKET_FILTER_CFM);
3291 if (!cfm)
3292 return -EIO;
3293
3294 slsi_kfree_skb(cfm);
3295 return r;
3296 }
3297
3298 int slsi_mlme_set_pmk(struct slsi_dev *sdev, struct net_device *dev, const u8 *pmk, u16 pmklen)
3299 {
3300 struct netdev_vif *ndev_vif = netdev_priv(dev);
3301 struct sk_buff *req;
3302 struct sk_buff *cfm;
3303 int r = 0;
3304
3305 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
3306
3307 if (WARN_ON(!ndev_vif->activated))
3308 return -EINVAL;
3309 if (pmk)
3310 req = fapi_alloc(mlme_set_pmk_req, MLME_SET_PMK_REQ, ndev_vif->ifnum, pmklen);
3311 else
3312 req = fapi_alloc(mlme_set_pmk_req, MLME_SET_PMK_REQ, ndev_vif->ifnum, 0);
3313
3314 if (!req)
3315 return -ENOMEM;
3316 if (pmk)
3317 fapi_append_data(req, pmk, pmklen);
3318
3319 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_pmk_req(vif:%u, pmklen:%d)\n", ndev_vif->ifnum, pmklen);
3320 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_PMK_CFM);
3321 if (!cfm)
3322 return -EIO;
3323
3324 if (fapi_get_u16(cfm, u.mlme_set_pmk_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3325 SLSI_NET_ERR(dev, "mlme_set_pmk_cfm(result:0x%04x) ERROR\n",
3326 fapi_get_u16(cfm, u.mlme_set_pmk_cfm.result_code));
3327 r = -EINVAL;
3328 }
3329 slsi_kfree_skb(cfm);
3330 return r;
3331 }
3332
3333 int slsi_mlme_roam(struct slsi_dev *sdev, struct net_device *dev, const u8 *bssid, u16 freq)
3334 {
3335 struct netdev_vif *ndev_vif = netdev_priv(dev);
3336 struct sk_buff *req;
3337 struct sk_buff *cfm;
3338 int r = 0;
3339
3340 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
3341 if (WARN_ON(!ndev_vif->activated))
3342 return -EINVAL;
3343
3344 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_roam_req(vif:%u, bssid:%pM, freq:%d)\n", ndev_vif->ifnum, bssid, freq);
3345 req = fapi_alloc(mlme_roam_req, MLME_ROAM_REQ, ndev_vif->ifnum, 0);
3346 if (!req)
3347 return -ENOMEM;
3348 fapi_set_memcpy(req, u.mlme_roam_req.bssid, bssid);
3349 fapi_set_u16(req, u.mlme_roam_req.channel_frequency, SLSI_FREQ_HOST_TO_FW(freq));
3350 atomic_set(&ndev_vif->sta.drop_roamed_ind, 1);
3351 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_ROAM_CFM);
3352 atomic_set(&ndev_vif->sta.drop_roamed_ind, 0);
3353 if (!cfm)
3354 return -EIO;
3355 if (fapi_get_u16(cfm, u.mlme_roam_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3356 SLSI_NET_ERR(dev, "mlme_roam_cfm(result:0x%04x) ERROR\n",
3357 fapi_get_u16(cfm, u.mlme_roam_cfm.result_code));
3358 r = -EINVAL;
3359 }
3360 slsi_kfree_skb(cfm);
3361 ndev_vif->sta.roam_in_progress = true;
3362 return r;
3363 }
3364
3365 int slsi_mlme_set_cached_channels(struct slsi_dev *sdev, struct net_device *dev, u32 channels_count, u8 *channels)
3366 {
3367 struct netdev_vif *ndev_vif = netdev_priv(dev);
3368 struct sk_buff *req;
3369 struct sk_buff *cfm;
3370 u8 *p;
3371 int r = 0;
3372 size_t channel_ie = 0;
3373 int i;
3374 const u8 channels_list_ie_header[] = {
3375 0xDD, /* Element ID: Vendor Specific */
3376 0x05, /* Length: actual length will be updated later */
3377 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
3378 0x01, /* OUI Type: Scan parameters */
3379 0x02 /* OUI Subtype: channel list */
3380 };
3381
3382 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
3383 if (WARN_ON(!ndev_vif->activated))
3384 return -EINVAL;
3385
3386 if (channels_count) {
3387 channel_ie += 6 + (channels_count * SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE);
3388 req = fapi_alloc(mlme_set_cached_channels_req, MLME_SET_CACHED_CHANNELS_REQ, ndev_vif->ifnum, channel_ie);
3389 } else {
3390 req = fapi_alloc(mlme_set_cached_channels_req, MLME_SET_CACHED_CHANNELS_REQ, ndev_vif->ifnum, 0);
3391 }
3392 if (!req)
3393 return -ENOMEM;
3394
3395 if (channels_count) {
3396 u16 freq_fw_unit;
3397 u8 *channels_list_ie = fapi_append_data(req, channels_list_ie_header, sizeof(channels_list_ie_header));
3398
3399 if (!channels_list_ie) {
3400 SLSI_WARN(sdev, "channel list IE append failed\n");
3401 slsi_kfree_skb(req);
3402 return -EINVAL;
3403 }
3404
3405 for (i = 0; i < channels_count; i++) {
3406 SLSI_NET_DBG3(dev, SLSI_MLME, "request for channels %d\n", channels[i]);
3407 p = fapi_append_data(req, NULL, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE);
3408 if (!p) {
3409 slsi_kfree_skb(req);
3410 return -EINVAL;
3411 }
3412 freq_fw_unit = 2 * ieee80211_channel_to_frequency(channels[i], (channels[i] <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ);
3413 freq_fw_unit = cpu_to_le16(freq_fw_unit);
3414 memcpy(p, &freq_fw_unit, sizeof(freq_fw_unit));
3415
3416 p[2] = FAPI_SCANPOLICY_2_4GHZ | FAPI_SCANPOLICY_5GHZ;
3417
3418 channels_list_ie[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE;
3419 }
3420 }
3421
3422 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_cached_channels_req(vif:%d)\n", ndev_vif->ifnum);
3423 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_CACHED_CHANNELS_CFM);
3424 if (!cfm)
3425 return -EIO;
3426
3427 if (fapi_get_u16(cfm, u.mlme_set_cached_channels_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3428 SLSI_NET_ERR(dev, "mlme_set_cached_channels_cfm(result:0x%04x) ERROR\n",
3429 fapi_get_u16(cfm, u.mlme_set_cached_channels_cfm.result_code));
3430 r = -EINVAL;
3431 }
3432
3433 slsi_kfree_skb(cfm);
3434 return r;
3435 }
3436
3437 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
3438 int slsi_mlme_set_acl(struct slsi_dev *sdev, struct net_device *dev, u16 ifnum, const struct cfg80211_acl_data *params)
3439 {
3440 struct sk_buff *req;
3441 struct sk_buff *cfm;
3442 size_t mac_acl_size = 0;
3443 int i, r = 0;
3444
3445 mac_acl_size = sizeof((params->mac_addrs[0])) * (params->n_acl_entries);
3446 req = fapi_alloc(mlme_set_acl_req, MLME_SET_ACL_REQ, ifnum, mac_acl_size);
3447 if (!req) {
3448 SLSI_NET_ERR(dev, "fapi alloc failure\n");
3449 return -ENOMEM;
3450 }
3451 fapi_set_u16(req, u.mlme_set_acl_req.entries, params->n_acl_entries);
3452 fapi_set_u16(req, u.mlme_set_acl_req.acl_policy, params->acl_policy);
3453
3454 for (i = 0; i < params->n_acl_entries; i++)
3455 fapi_append_data(req, params->mac_addrs[i].addr, sizeof((params->mac_addrs[i])));
3456
3457 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_acl_req(vif:%u, n_acl_entries:%d)\n", ifnum, params->n_acl_entries);
3458
3459 if (ifnum)
3460 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_ACL_CFM);
3461 else
3462 cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_SET_ACL_CFM);
3463 if (!cfm)
3464 return -EIO;
3465
3466 if (fapi_get_u16(cfm, u.mlme_set_acl_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3467 SLSI_NET_ERR(dev, "mlme_set_acl_cfm(result:0x%04x) ERROR\n",
3468 fapi_get_u16(cfm, u.mlme_set_acl_cfm.result_code));
3469 r = -EINVAL;
3470 }
3471
3472 slsi_kfree_skb(cfm);
3473 return r;
3474 }
3475 #endif
3476
3477 int slsi_mlme_set_traffic_parameters(struct slsi_dev *sdev, struct net_device *dev, u16 user_priority, u16 medium_time, u16 minimun_data_rate, u8 *mac)
3478 {
3479 struct netdev_vif *ndev_vif = netdev_priv(dev);
3480 struct sk_buff *req;
3481 struct sk_buff *rx;
3482 int r = 0;
3483
3484 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
3485
3486 if (WARN_ON(!ndev_vif->activated))
3487 return -EINVAL;
3488
3489 if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION && ndev_vif->iftype == NL80211_IFTYPE_STATION))
3490 return -EINVAL;
3491
3492 req = fapi_alloc(mlme_set_traffic_parameters_req, MLME_SET_TRAFFIC_PARAMETERS_REQ, ndev_vif->ifnum, 0);
3493 if (!req)
3494 return -ENOMEM;
3495
3496 fapi_set_u16(req, u.mlme_set_traffic_parameters_req.user_priority, user_priority);
3497 fapi_set_u16(req, u.mlme_set_traffic_parameters_req.medium_time, medium_time);
3498 fapi_set_u16(req, u.mlme_set_traffic_parameters_req.minimum_data_rate, minimun_data_rate);
3499
3500 if (mac)
3501 fapi_set_memcpy(req, u.mlme_set_traffic_parameters_req.peer_address, mac);
3502 else
3503 fapi_set_memset(req, u.mlme_set_traffic_parameters_req.peer_address, 0);
3504
3505 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_set_traffic_parameters_req(vif:%u, user_priority:%d, medium_time:%d)\n", ndev_vif->ifnum, user_priority, medium_time);
3506 rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_TRAFFIC_PARAMETERS_CFM);
3507 if (!rx)
3508 return -EIO;
3509
3510 if (fapi_get_u16(rx, u.mlme_set_traffic_parameters_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3511 SLSI_NET_ERR(dev, "mlme_set_traffic_parameters_cfm(result:0x%04x) ERROR\n",
3512 fapi_get_u16(rx, u.mlme_set_traffic_parameters_cfm.result_code));
3513 r = -EINVAL;
3514 }
3515
3516 return r;
3517 }
3518
3519 int slsi_mlme_del_traffic_parameters(struct slsi_dev *sdev, struct net_device *dev, u16 user_priority)
3520 {
3521 struct netdev_vif *ndev_vif = netdev_priv(dev);
3522 struct sk_buff *req;
3523 struct sk_buff *rx;
3524 int r = 0;
3525
3526 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
3527
3528 if (WARN_ON(!ndev_vif->activated))
3529 return -EINVAL;
3530
3531 if (WARN_ON(ndev_vif->vif_type != FAPI_VIFTYPE_STATION && ndev_vif->iftype == NL80211_IFTYPE_STATION))
3532 return -EINVAL;
3533
3534 req = fapi_alloc(mlme_del_traffic_parameters_req, MLME_DEL_TRAFFIC_PARAMETERS_REQ, ndev_vif->ifnum, 0);
3535 if (!req)
3536 return -ENOMEM;
3537
3538 fapi_set_u16(req, u.mlme_del_traffic_parameters_req.user_priority, user_priority);
3539
3540 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_del_traffic_parameters_req(vif:%u, user_priority:%d)\n", ndev_vif->ifnum, user_priority);
3541 rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_DEL_TRAFFIC_PARAMETERS_CFM);
3542 if (!rx)
3543 return -EIO;
3544
3545 if (fapi_get_u16(rx, u.mlme_del_traffic_parameters_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3546 SLSI_NET_ERR(dev, "mlme_del_traffic_parameters_cfm(result:0x%04x) ERROR\n",
3547 fapi_get_u16(rx, u.mlme_del_traffic_parameters_cfm.result_code));
3548 r = -EINVAL;
3549 }
3550
3551 return r;
3552 }
3553
3554 int slsi_mlme_set_ext_capab(struct slsi_dev *sdev, struct net_device *dev, struct slsi_mib_value *mib_val)
3555 {
3556 struct slsi_mib_data mib_data = { 0, NULL };
3557 int error = 0;
3558
3559 error = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES, mib_val->u.octetValue.dataLength, mib_val->u.octetValue.data, 0);
3560 if (error != SLSI_MIB_STATUS_SUCCESS) {
3561 error = -ENOMEM;
3562 goto exit;
3563 }
3564
3565 if (WARN_ON(mib_data.dataLength == 0)) {
3566 error = -EINVAL;
3567 goto exit;
3568 }
3569
3570 error = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength);
3571 kfree(mib_data.data);
3572
3573 if (!error)
3574 return 0;
3575
3576 exit:
3577 SLSI_ERR(sdev, "Error in setting ext capab. error = %d\n", error);
3578 return error;
3579 }
3580
3581 int slsi_mlme_set_hs2_ext_cap(struct slsi_dev *sdev, struct net_device *dev, const u8 *ies, int ie_len)
3582 {
3583 struct slsi_mib_entry mib_entry;
3584 struct slsi_mib_data mibreq = { 0, NULL };
3585 struct slsi_mib_data mibrsp = { 0, NULL };
3586 const u8 *ext_capab_ie;
3587 int r = 0;
3588 int rx_length = 0;
3589 int len = 0;
3590
3591 slsi_mib_encode_get(&mibreq, SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES, 0);
3592
3593 /* 5 (header) + 9 (data) + 2 (mlme expects 16 (??))*/
3594 mibrsp.dataLength = 16;
3595 mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL);
3596
3597 if (!mibrsp.data) {
3598 SLSI_ERR(sdev, "Failed to alloc for Mib response\n");
3599 kfree(mibreq.data);
3600 return -ENOMEM;
3601 }
3602
3603 r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength,
3604 mibrsp.data, mibrsp.dataLength, &rx_length);
3605 kfree(mibreq.data);
3606
3607 if (r == 0) {
3608 mibrsp.dataLength = rx_length;
3609 len = slsi_mib_decode(&mibrsp, &mib_entry);
3610 if (len == 0) {
3611 SLSI_ERR(sdev, "Mib decode error\n");
3612 r = -EINVAL;
3613 goto exit;
3614 }
3615 } else {
3616 SLSI_NET_DBG1(dev, SLSI_MLME, "Mib read failed (error: %d)\n", r);
3617 goto exit;
3618 }
3619
3620 ext_capab_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ie_len);
3621
3622 if (ext_capab_ie) {
3623 u8 ext_capab_ie_len = ext_capab_ie[1];
3624
3625 ext_capab_ie += 2; /* skip the EID and length*/
3626
3627 /*BSS Transition bit is bit 19 ,ie length must be >= 3 */
3628 if ((ext_capab_ie_len >= 3) && (ext_capab_ie[2] & SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED))
3629 mib_entry.value.u.octetValue.data[2] |= SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED;
3630 else
3631 mib_entry.value.u.octetValue.data[2] &= ~SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED;
3632
3633 /*interworking bit is bit 31 ,ie length must be >= 4 */
3634 if ((ext_capab_ie_len >= 4) && (ext_capab_ie[3] & SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED))
3635 mib_entry.value.u.octetValue.data[3] |= SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED;
3636 else
3637 mib_entry.value.u.octetValue.data[3] &= ~SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED;
3638
3639 /*QoS MAP is bit 32 ,ie length must be >= 5 */
3640 if ((ext_capab_ie_len >= 5) && (ext_capab_ie[4] & SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED))
3641 mib_entry.value.u.octetValue.data[4] |= SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED;
3642 else
3643 mib_entry.value.u.octetValue.data[4] &= ~SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED;
3644
3645 /*WNM- Notification bit is bit 46 ,ie length must be >= 6 */
3646 if ((ext_capab_ie_len >= 6) && (ext_capab_ie[5] & SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED))
3647 mib_entry.value.u.octetValue.data[5] |= SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED;
3648 else
3649 mib_entry.value.u.octetValue.data[5] &= ~SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED;
3650 } else {
3651 mib_entry.value.u.octetValue.data[2] &= ~SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED;
3652 mib_entry.value.u.octetValue.data[3] &= ~SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED;
3653 mib_entry.value.u.octetValue.data[4] &= ~SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED;
3654 mib_entry.value.u.octetValue.data[5] &= ~SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED;
3655 }
3656
3657 r = slsi_mlme_set_ext_capab(sdev, dev, &mib_entry.value);
3658 exit:
3659 kfree(mibrsp.data);
3660 return r;
3661 }
3662
3663 int slsi_mlme_tdls_peer_resp(struct slsi_dev *sdev, struct net_device *dev, u16 pid, u16 tdls_event)
3664 {
3665 struct netdev_vif *ndev_vif = netdev_priv(dev);
3666 struct sk_buff *req;
3667 struct sk_buff *cfm;
3668
3669 req = fapi_alloc(mlme_tdls_peer_res, MLME_TDLS_PEER_RES, ndev_vif->ifnum, 0);
3670 if (!req)
3671 return -ENOMEM;
3672
3673 fapi_set_u16(req, u.mlme_tdls_peer_res.peer_index, pid);
3674 fapi_set_u16(req, u.mlme_tdls_peer_res.tdls_event, tdls_event);
3675
3676 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_tdls_peer_res(vif:%d)\n", ndev_vif->ifnum);
3677 cfm = slsi_mlme_req_no_cfm(sdev, dev, req);
3678 WARN_ON(cfm);
3679
3680 return 0;
3681 }
3682
3683 int slsi_mlme_tdls_action(struct slsi_dev *sdev, struct net_device *dev, const u8 *peer, int action, u16 center_freq, u16 chan_info)
3684 {
3685 struct netdev_vif *ndev_vif = netdev_priv(dev);
3686 struct sk_buff *req;
3687 struct sk_buff *cfm;
3688 int r = 0;
3689
3690 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_tdls_action_req(action:%u)\n", action);
3691 req = fapi_alloc(mlme_tdls_action_req, MLME_TDLS_ACTION_REQ, ndev_vif->ifnum, 0);
3692 if (!req)
3693 return -ENOMEM;
3694
3695 center_freq = SLSI_FREQ_HOST_TO_FW(center_freq);
3696
3697 fapi_set_memcpy(req, u.mlme_tdls_action_req.peer_sta_address, peer);
3698 fapi_set_u16(req, u.mlme_tdls_action_req.tdls_action, action);
3699 fapi_set_u16(req, u.mlme_tdls_action_req.channel_frequency, center_freq);
3700 fapi_set_u16(req, u.mlme_tdls_action_req.channel_information, chan_info);
3701
3702 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_TDLS_ACTION_CFM);
3703 if (!cfm)
3704 return -EIO;
3705
3706 if (fapi_get_u16(cfm, u.mlme_tdls_action_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3707 SLSI_NET_ERR(dev, "mlme_tdls_action_cfm(result:0x%04x) ERROR\n",
3708 fapi_get_u16(cfm, u.mlme_tdls_action_cfm.result_code));
3709 r = -EINVAL;
3710 }
3711
3712 slsi_kfree_skb(cfm);
3713
3714 return r;
3715 }
3716
3717 int slsi_mlme_reassociate(struct slsi_dev *sdev, struct net_device *dev)
3718 {
3719 struct netdev_vif *ndev_vif = netdev_priv(dev);
3720 struct sk_buff *req;
3721 struct sk_buff *cfm;
3722 int r = 0;
3723
3724 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
3725 if (WARN_ON(!ndev_vif->activated))
3726 return -EINVAL;
3727
3728 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_reassoc_req(vif:%u)\n", ndev_vif->ifnum);
3729 req = fapi_alloc(mlme_reassociate_req, MLME_REASSOCIATE_REQ, ndev_vif->ifnum, 0);
3730 if (!req)
3731 return -ENOMEM;
3732
3733 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_REASSOCIATE_CFM);
3734 if (!cfm)
3735 return -EIO;
3736
3737 if (fapi_get_u16(cfm, u.mlme_reassociate_cfm.result_code) == FAPI_RESULTCODE_HOST_REQUEST_SUCCESS) {
3738 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_reassoc_cfm(result:0x%04x)\n",
3739 fapi_get_u16(cfm, u.mlme_reassociate_cfm.result_code));
3740 } else {
3741 SLSI_NET_ERR(dev, "mlme_reassoc_cfm(result:0x%04x) ERROR\n",
3742 fapi_get_u16(cfm, u.mlme_reassociate_cfm.result_code));
3743 r = -EINVAL;
3744 }
3745 slsi_kfree_skb(cfm);
3746 return r;
3747 }
3748
3749 void slsi_mlme_reassociate_resp(struct slsi_dev *sdev, struct net_device *dev)
3750 {
3751 struct netdev_vif *ndev_vif = netdev_priv(dev);
3752 struct sk_buff *req;
3753 struct sk_buff *cfm;
3754
3755 if (slsi_is_test_mode_enabled()) {
3756 SLSI_NET_INFO(dev, "Skip sending signal, WlanLite FW does not support MLME_REASSOCIATE_RESP\n");
3757 return;
3758 }
3759
3760 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_reassociate_resp(vif:%d)\n", ndev_vif->ifnum);
3761 req = fapi_alloc(mlme_reassociate_res, MLME_REASSOCIATE_RES, ndev_vif->ifnum, 0);
3762 if (!req)
3763 return;
3764
3765 cfm = slsi_mlme_req_no_cfm(sdev, dev, req);
3766 WARN_ON(cfm);
3767 }
3768
3769 int slsi_mlme_add_range_req(struct slsi_dev *sdev, u8 count,
3770 struct slsi_rtt_config *nl_rtt_params, u16 rtt_id, u16 vif_idx, u8 *source_addr)
3771 {
3772 struct sk_buff *req;
3773 struct sk_buff *rx;
3774 int r = 0, i;
3775 size_t alloc_data_size = 0;
3776 u8 fapi_ie_generic[] = { 0xdd, 0x1c, 0x00, 0x16, 0x32, 0x0a, 0x01 };
3777 /* calculate data size */
3778 alloc_data_size += count * (fapi_ie_generic[1] + 2);
3779
3780 req = fapi_alloc(mlme_add_range_req, MLME_ADD_RANGE_REQ, 0, alloc_data_size);
3781 if (!req) {
3782 SLSI_ERR(sdev, "failed to alloc %zd\n", alloc_data_size);
3783 return -ENOMEM;
3784 }
3785 SLSI_DBG2(sdev, SLSI_MLME, "count:%d allocated data size: %d, source_addr:%pM\n",
3786 count, alloc_data_size, source_addr);
3787 /*fill the data */
3788 fapi_set_u16(req, u.mlme_add_range_req.vif, vif_idx);
3789 fapi_set_u16(req, u.mlme_add_range_req.rtt_id, rtt_id);
3790 fapi_set_memcpy(req, u.mlme_add_range_req.device_address, source_addr);
3791 for (i = 0; i < count; i++) {
3792 fapi_append_data(req, fapi_ie_generic, sizeof(fapi_ie_generic));
3793 fapi_append_data(req, nl_rtt_params[i].peer_addr, ETH_ALEN);
3794 fapi_append_data(req, (u8 *)&nl_rtt_params[i].type, 2);
3795 fapi_append_data(req, (u8 *)&nl_rtt_params[i].channel_freq, 2);
3796 fapi_append_data(req, (u8 *)&nl_rtt_params[i].burst_period, 1);
3797 fapi_append_data(req, (u8 *)&nl_rtt_params[i].num_burst, 1);
3798 fapi_append_data(req, (u8 *)&nl_rtt_params[i].num_frames_per_burst, 1);
3799 fapi_append_data(req, (u8 *)&nl_rtt_params[i].num_retries_per_ftmr, 1);
3800 fapi_append_data(req, (u8 *)&nl_rtt_params[i].burst_duration, 1);
3801 fapi_append_data(req, (u8 *)&nl_rtt_params[i].preamble, 2);
3802 fapi_append_data(req, (u8 *)&nl_rtt_params[i].bw, 2);
3803 fapi_append_data(req, (u8 *)&nl_rtt_params[i].LCI_request, 2);
3804 fapi_append_data(req, (u8 *)&nl_rtt_params[i].LCR_request, 2);
3805 }
3806 rx = slsi_mlme_req_cfm(sdev, NULL, req, MLME_ADD_RANGE_CFM);
3807 SLSI_DBG2(sdev, SLSI_MLME, "(After mlme req cfm for rtt config)\n");
3808 if (!rx)
3809 return -EIO;
3810 if (fapi_get_u16(rx, u.mlme_add_range_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3811 SLSI_ERR(sdev, "mlme_add_range_cfm(ERROR:0x%04x)",
3812 fapi_get_u16(rx, u.mlme_add_range_cfm.result_code));
3813 r = -EINVAL;
3814 }
3815
3816 slsi_kfree_skb(rx);
3817 return r;
3818 }
3819
3820 bool slsi_del_range_cfm_validate(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *cfm)
3821 {
3822 int result = fapi_get_u16(cfm, u.mlme_del_range_cfm.result_code);
3823 bool r = false;
3824
3825 SLSI_UNUSED_PARAMETER(sdev);
3826
3827 if (WARN_ON(!dev))
3828 goto exit;
3829
3830 if (result == FAPI_RESULTCODE_SUCCESS)
3831 r = true;
3832 else
3833 SLSI_NET_ERR(dev, "mlme_del_range_cfm(result:0x%04x) ERROR\n", result);
3834
3835 exit:
3836 slsi_kfree_skb(cfm);
3837 return r;
3838 }
3839
3840 int slsi_mlme_del_range_req(struct slsi_dev *sdev, struct net_device *dev, u16 count,
3841 u8 *addr, u16 rtt_id)
3842 {
3843 struct sk_buff *req;
3844 struct sk_buff *rx;
3845 u16 *rtt_vif_idx = sdev->rtt_vif;
3846 int r = 0, i;
3847 size_t alloc_data_size = 0;
3848
3849 /* calculate data size-->2 bytes for vif */
3850 alloc_data_size += count * sizeof(ETH_ALEN);
3851 /* Alloc data size */
3852 req = fapi_alloc(mlme_del_range_req, MLME_DEL_RANGE_REQ, 0, alloc_data_size);
3853 if (!req) {
3854 SLSI_ERR(sdev, "failed to alloc %zd\n", alloc_data_size);
3855 return -ENOMEM;
3856 }
3857 /*fill the data */
3858 fapi_set_u16(req, u.mlme_del_range_req.vif, rtt_vif_idx[rtt_id]);
3859 fapi_set_u16(req, u.mlme_del_range_req.rtt_id, rtt_id);
3860 fapi_set_u16(req, u.mlme_del_range_req.entries, count);
3861 for (i = 0; i < count; i++)
3862 fapi_append_data(req, &addr[i * ETH_ALEN], ETH_ALEN);
3863
3864 rx = slsi_mlme_req_cfm_ind(sdev, dev, req, MLME_DEL_RANGE_CFM, MLME_RANGE_IND, slsi_del_range_cfm_validate);
3865 sdev->rtt_vif[rtt_id] = -1;
3866 if (!rx) {
3867 SLSI_NET_ERR(dev, "mlme_del_range_cfm() ERROR\n");
3868 slsi_kfree_skb(rx);
3869 return -EINVAL;
3870 }
3871 slsi_kfree_skb(rx);
3872 return r;
3873 }
3874
3875 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
3876 #define SLSI_FAPI_EPNO_NETWORK_MIN_SIZE (3)
3877 int slsi_mlme_set_pno_list(struct slsi_dev *sdev, int count,
3878 struct slsi_epno_param *epno_param, struct slsi_epno_hs2_param *epno_hs2_param)
3879 {
3880 struct sk_buff *req;
3881 struct sk_buff *rx;
3882 int r = 0;
3883 size_t alloc_data_size = 0;
3884 u32 i, j;
3885 u8 fapi_ie_generic[] = { 0xdd, 0, 0x00, 0x16, 0x32, 0x01, 0x00 };
3886 u8 *buff_ptr, *ie_start_pos;
3887
3888 if (count) {
3889 /* calculate data size */
3890 if (epno_param) {
3891 alloc_data_size += sizeof(fapi_ie_generic) + SLSI_FAPI_EPNO_NETWORK_MIN_SIZE * count + 11;
3892 for (i = 0; i < count; i++)
3893 alloc_data_size += epno_param->epno_ssid[i].ssid_len;
3894 } else if (epno_hs2_param) {
3895 for (i = 0; i < count; i++) {
3896 /* fapi_ie_generic + Network_block_ID(1) + Realm_length(1) + realm_data(x)
3897 * + Roaming_Consortium_Count(1) + Roaming Consortium data(16 * 8) +
3898 * PLMN length(1) + PLMN data(6)
3899 */
3900 if (strlen(epno_hs2_param->realm))
3901 alloc_data_size += sizeof(fapi_ie_generic) + 1 + 1 + (strlen(epno_hs2_param->realm) + 1)
3902 + 1 + 16 * 8 + 1 + 6;
3903 else
3904 alloc_data_size += sizeof(fapi_ie_generic) + 1 + 1 + 0
3905 + 1 + 16 * 8 + 1 + 6;
3906 }
3907 }
3908 }
3909
3910 /* Alloc data size */
3911 req = fapi_alloc(mlme_set_pno_list_req, MLME_SET_PNO_LIST_REQ, 0, alloc_data_size);
3912 if (!req) {
3913 SLSI_ERR(sdev, "failed to alloc %zd\n", alloc_data_size);
3914 return -ENOMEM;
3915 }
3916 if (count) {
3917 /* Fill data */
3918 if (epno_param) {
3919 fapi_ie_generic[1] = alloc_data_size - 2;
3920 fapi_ie_generic[6] = 9; /* OUI */
3921 fapi_append_data(req, fapi_ie_generic, sizeof(fapi_ie_generic));
3922 fapi_append_data(req, (u8 *)epno_param, (sizeof(*epno_param) - 1));
3923 for (i = 0; i < count; i++) {
3924 fapi_append_data(req, (u8 *)&epno_param->epno_ssid[i].flags, 2);
3925 fapi_append_data(req, (u8 *)&epno_param->epno_ssid[i].ssid_len, 1);
3926 fapi_append_data(req, (u8 *)epno_param->epno_ssid[i].ssid,
3927 epno_param->epno_ssid[i].ssid_len);
3928 }
3929 } else if (epno_hs2_param) {
3930 u8 realm_length;
3931 u8 roaming_consortium_count = 16;
3932 u8 plmn_length = 6;
3933 u8 plmn_digit[6];
3934
3935 fapi_ie_generic[6] = 0x10; /* OUI subtype = Passpoint Network */
3936 for (i = 0; i < count; i++) {
3937 buff_ptr = fapi_append_data(req, fapi_ie_generic, sizeof(fapi_ie_generic));
3938 if (!buff_ptr) {
3939 SLSI_ERR(sdev, "failed append data\n");
3940 slsi_kfree_skb(req);
3941 return -EINVAL;
3942 }
3943 ie_start_pos = buff_ptr;
3944
3945 fapi_append_data(req, (u8 *)&epno_hs2_param[i].id, 1);
3946
3947 realm_length = strlen(epno_hs2_param[i].realm);
3948 if (realm_length) {
3949 realm_length++;
3950 fapi_append_data(req, &realm_length, 1);
3951 fapi_append_data(req, epno_hs2_param[i].realm, realm_length);
3952 } else {
3953 fapi_append_data(req, &realm_length, 1);
3954 }
3955
3956 fapi_append_data(req, &roaming_consortium_count, 1);
3957 fapi_append_data(req, (u8 *)&epno_hs2_param[i].roaming_consortium_ids, 16 * 8);
3958
3959 fapi_append_data(req, &plmn_length, 1);
3960 for (j = 0; j < 3; j++) {
3961 plmn_digit[j * 2] = epno_hs2_param[i].plmn[i] & 0x0F;
3962 plmn_digit[(j * 2) + 1] = epno_hs2_param[i].plmn[i] & 0xF0 >> 4;
3963 }
3964 buff_ptr = fapi_append_data(req, plmn_digit, sizeof(plmn_digit));
3965 if (!buff_ptr) {
3966 SLSI_ERR(sdev, "failed append data\n");
3967 slsi_kfree_skb(req);
3968 return -EINVAL;
3969 }
3970
3971 buff_ptr += sizeof(plmn_digit);
3972 ie_start_pos[1] = buff_ptr - ie_start_pos - 2; /* fill ie length field */
3973 }
3974 }
3975 }
3976
3977 /* Send signal */
3978 /* Use the Global sig_wait not the Interface specific for mlme-set-pno.list */
3979 rx = slsi_mlme_req_cfm(sdev, NULL, req, MLME_SET_PNO_LIST_CFM);
3980 if (!rx)
3981 return -EIO;
3982 if (fapi_get_u16(rx, u.mlme_set_pno_list_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
3983 SLSI_ERR(sdev, "mlme_set_pno_list_cfm(ERROR:0x%04x)",
3984 fapi_get_u16(rx, u.mlme_set_pno_list_cfm.result_code));
3985 r = -EINVAL;
3986 }
3987 slsi_kfree_skb(rx);
3988 return r;
3989 }
3990
3991 int slsi_mlme_start_link_stats_req(struct slsi_dev *sdev, u16 mpdu_size_threshold, bool aggressive_stats_enabled)
3992 {
3993 struct sk_buff *req;
3994 struct sk_buff *cfm;
3995 int r = 0;
3996
3997 req = fapi_alloc(mlme_start_link_statistics_req, MLME_START_LINK_STATISTICS_REQ, 0, 0);
3998 if (!req) {
3999 SLSI_ERR(sdev, "memory allocation failed for signal\n");
4000 return -ENOMEM;
4001 }
4002
4003 fapi_set_u16(req, u.mlme_start_link_statistics_req.mpdu_size_threshold, mpdu_size_threshold);
4004 fapi_set_u16(req, u.mlme_start_link_statistics_req.aggressive_statistics_gathering_enabled,
4005 aggressive_stats_enabled);
4006
4007 SLSI_DBG2(sdev, SLSI_MLME, "(mpdu_size_threshold:%d, aggressive_stats_enabled:%d)\n",
4008 mpdu_size_threshold, aggressive_stats_enabled);
4009 cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_START_LINK_STATISTICS_CFM);
4010 if (!cfm)
4011 return -EIO;
4012
4013 if (fapi_get_u16(cfm, u.mlme_start_link_statistics_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4014 SLSI_ERR(sdev, "mlme_start_link_statistics_cfm (result:0x%04x) ERROR\n",
4015 fapi_get_u16(cfm, u.mlme_start_link_statistics_cfm.result_code));
4016 r = -EINVAL;
4017 }
4018
4019 slsi_kfree_skb(cfm);
4020 return r;
4021 }
4022
4023 int slsi_mlme_stop_link_stats_req(struct slsi_dev *sdev, u16 stats_stop_mask)
4024 {
4025 struct sk_buff *req;
4026 struct sk_buff *cfm;
4027 int r = 0;
4028
4029 req = fapi_alloc(mlme_stop_link_statistics_req, MLME_STOP_LINK_STATISTICS_REQ, 0, 0);
4030 if (!req) {
4031 SLSI_ERR(sdev, "memory allocation failed for signal\n");
4032 return -ENOMEM;
4033 }
4034
4035 fapi_set_u16(req, u.mlme_stop_link_statistics_req.statistics_stop_bitmap, stats_stop_mask);
4036
4037 SLSI_DBG2(sdev, SLSI_MLME, "statistics_stop_bitmap:%d\n", stats_stop_mask);
4038 cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_STOP_LINK_STATISTICS_CFM);
4039 if (!cfm)
4040 return -EIO;
4041
4042 if (fapi_get_u16(cfm, u.mlme_stop_link_statistics_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4043 SLSI_ERR(sdev, "mlme_stop_link_statistics_cfm (result:0x%04x) ERROR\n",
4044 fapi_get_u16(cfm, u.mlme_stop_link_statistics_cfm.result_code));
4045 r = -EINVAL;
4046 }
4047 slsi_kfree_skb(cfm);
4048 return r;
4049 }
4050 #endif
4051
4052 int slsi_mlme_set_rssi_monitor(struct slsi_dev *sdev, struct net_device *dev, u8 enable, s8 low_rssi_threshold, s8 high_rssi_threshold)
4053 {
4054 struct netdev_vif *ndev_vif = netdev_priv(dev);
4055 struct sk_buff *req;
4056 struct sk_buff *cfm;
4057 int r = 0;
4058
4059 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_set_rssi_monitor(vif:%u), enable =%d, low_rssi_threshold = %d,high_rssi_threshold =%d\n",
4060 ndev_vif->ifnum, enable, low_rssi_threshold, high_rssi_threshold);
4061
4062 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
4063 req = fapi_alloc(mlme_monitor_rssi_req, MLME_MONITOR_RSSI_REQ, ndev_vif->ifnum, 0);
4064 if (!req) {
4065 SLSI_NET_ERR(dev, "fapi alloc failure\n");
4066 return -ENOMEM;
4067 }
4068
4069 fapi_set_u16(req, u.mlme_monitor_rssi_req.rssi_monitoring_enabled, enable);
4070 fapi_set_u16(req, u.mlme_monitor_rssi_req.low_rssi_threshold, low_rssi_threshold);
4071 fapi_set_u16(req, u.mlme_monitor_rssi_req.high_rssi_threshold, high_rssi_threshold);
4072
4073 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_MONITOR_RSSI_CFM);
4074 if (!cfm)
4075 return -EIO;
4076
4077 if (fapi_get_u16(cfm, u.mlme_monitor_rssi_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4078 SLSI_NET_ERR(dev, "mlme_monitor_rssi_cfm(result:0x%04x) ERROR\n", fapi_get_u16(cfm, u.mlme_monitor_rssi_cfm.result_code));
4079 r = -EINVAL;
4080 }
4081
4082 slsi_kfree_skb(cfm);
4083 return r;
4084 }
4085
4086 struct slsi_mib_value *slsi_read_mibs(struct slsi_dev *sdev, struct net_device *dev,
4087 struct slsi_mib_get_entry *mib_entries, int mib_count, struct slsi_mib_data *mibrsp)
4088 {
4089 struct slsi_mib_data mibreq = { 0, NULL };
4090 struct slsi_mib_value *values;
4091 int rx_length, r;
4092
4093 r = slsi_mib_encode_get_list(&mibreq, mib_count, mib_entries);
4094 if (r != SLSI_MIB_STATUS_SUCCESS) {
4095 SLSI_WARN(sdev, "slsi_mib_encode_get_list fail %d\n", r);
4096 return NULL;
4097 }
4098
4099 r = slsi_mlme_get(sdev, dev, mibreq.data, mibreq.dataLength, mibrsp->data, mibrsp->dataLength, &rx_length);
4100 kfree(mibreq.data);
4101
4102 if (r != 0) {
4103 SLSI_ERR(sdev, "Mib (err:%d)\n", r);
4104 return NULL;
4105 }
4106
4107 mibrsp->dataLength = (u32)rx_length;
4108 values = slsi_mib_decode_get_list(mibrsp, mib_count, mib_entries);
4109 if (!values)
4110 SLSI_WARN(sdev, "decode error\n");
4111 return values;
4112 }
4113
4114 int slsi_mlme_set_ctwindow(struct slsi_dev *sdev, struct net_device *dev, unsigned int ct_param)
4115 {
4116 struct netdev_vif *ndev_vif;
4117 struct sk_buff *req;
4118 struct sk_buff *cfm;
4119 int r = 0;
4120
4121 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_set_ctwindow(ct_param = %d)\n", ct_param);
4122
4123 ndev_vif = netdev_priv(dev);
4124
4125 req = fapi_alloc(mlme_set_ctwindow_req, MLME_SET_CTWINDOW_REQ, ndev_vif->ifnum, 0);
4126 if (!req)
4127 return -ENOMEM;
4128
4129 fapi_set_u16(req, u.mlme_set_ctwindow_req.ctwindow, ct_param);
4130
4131 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_CTWINDOW_CFM);
4132 if (!cfm)
4133 return -EIO;
4134
4135 if (fapi_get_u16(cfm, u.mlme_set_ctwindow_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4136 SLSI_NET_ERR(dev, "mlme_set_ctwindow_cfm(result:0x%04x) ERROR\n",
4137 fapi_get_u16(cfm, u.mlme_set_ctwindow_cfm.result_code));
4138 r = -EINVAL;
4139 }
4140 slsi_kfree_skb(cfm);
4141 return r;
4142 }
4143
4144 int slsi_mlme_set_p2p_noa(struct slsi_dev *sdev, struct net_device *dev, unsigned int noa_count,
4145 unsigned int interval, unsigned int duration)
4146 {
4147 struct netdev_vif *ndev_vif;
4148 struct sk_buff *req;
4149 struct sk_buff *cfm;
4150 int r = 0;
4151
4152 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_set_noa_req(noa_count = %d, interval = %d, duration = %d)\n",
4153 noa_count, interval, duration);
4154
4155 ndev_vif = netdev_priv(dev);
4156
4157 req = fapi_alloc(mlme_set_noa_req, MLME_SET_NOA_REQ, ndev_vif->ifnum, 0);
4158 if (!req)
4159 return -ENOMEM;
4160
4161 fapi_set_u16(req, u.mlme_set_noa_req.request_id, SLSI_NOA_CONFIG_REQUEST_ID);
4162 fapi_set_u16(req, u.mlme_set_noa_req.noa_count, noa_count);
4163 if (!interval)
4164 fapi_set_u32(req, u.mlme_set_noa_req.interval, (1 * 1024 * ndev_vif->ap.beacon_interval));
4165 else
4166 fapi_set_u32(req, u.mlme_set_noa_req.interval, interval * 1000);
4167 fapi_set_u32(req, u.mlme_set_noa_req.duration, duration * 1000);
4168
4169 cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_NOA_CFM);
4170 if (!cfm)
4171 return -EIO;
4172
4173 if (fapi_get_u16(cfm, u.mlme_set_noa_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4174 SLSI_NET_ERR(dev, "mlme_set_noa_cfm(result:0x%04x) ERROR\n",
4175 fapi_get_u16(cfm, u.mlme_set_noa_cfm.result_code));
4176 r = -EINVAL;
4177 }
4178 slsi_kfree_skb(cfm);
4179 return r;
4180 }
4181
4182 int slsi_mlme_set_host_state(struct slsi_dev *sdev, struct net_device *dev, u8 host_state)
4183 {
4184 struct sk_buff *req;
4185 struct sk_buff *cfm;
4186 int r = 0;
4187
4188 if (slsi_is_test_mode_enabled()) {
4189 SLSI_NET_INFO(dev, "Skip MLME_HOST_STATE_REQ in wlanlite mode\n");
4190 return -EOPNOTSUPP;
4191 }
4192
4193 SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_set_host_state(state =%d)\n", host_state);
4194
4195 req = fapi_alloc(mlme_host_state_req, MLME_HOST_STATE_REQ, 0, 0);
4196 if (!req) {
4197 SLSI_NET_ERR(dev, "fapi alloc failure\n");
4198 return -ENOMEM;
4199 }
4200
4201 fapi_set_u16(req, u.mlme_host_state_req.host_state, host_state);
4202
4203 cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_HOST_STATE_CFM);
4204 if (!cfm)
4205 return -EIO;
4206
4207 if (fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4208 SLSI_NET_ERR(dev, "mlme_host_state_cfm(result:0x%04x) ERROR\n",
4209 fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
4210 r = -EINVAL;
4211 }
4212
4213 slsi_kfree_skb(cfm);
4214 return r;
4215 }
4216
4217 int slsi_mlme_read_apf_request(struct slsi_dev *sdev, struct net_device *dev, u8 **host_dst, int *datalen)
4218 {
4219 struct netdev_vif *ndev_vif = netdev_priv(dev);
4220 struct sk_buff *req;
4221 struct sk_buff *rx;
4222 int r = 0;
4223
4224 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
4225
4226 if (!ndev_vif->activated) {
4227 SLSI_ERR(sdev, "ndev_vif is not activated\n");
4228 r = -EINVAL;
4229 goto exit;
4230 }
4231
4232 if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) {
4233 SLSI_ERR(sdev, "vif_type is not FAPI_VIFTYPE_STATION\n");
4234 r = -EINVAL;
4235 goto exit;
4236 }
4237
4238 req = fapi_alloc(mlme_read_apf_req, MLME_READ_APF_REQ, ndev_vif->ifnum, 0);
4239 if (!req) {
4240 r = -ENOMEM;
4241 goto exit;
4242 }
4243
4244 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_read_apf_req(vif:%u)\n", ndev_vif->ifnum);
4245 rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_READ_APF_CFM);
4246 if (!rx) {
4247 r = -EIO;
4248 goto exit;
4249 }
4250
4251 if (fapi_get_u16(rx, u.mlme_read_apf_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4252 SLSI_NET_ERR(dev, "mlme_read_apf_cfm(result:0x%04x) ERROR\n",
4253 fapi_get_u16(rx, u.mlme_read_apf_cfm.result_code));
4254 r = -EINVAL;
4255 }
4256
4257 *datalen = fapi_get_datalen(rx);
4258 *host_dst = fapi_get_data(rx);
4259
4260 exit:
4261 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
4262 return r;
4263 }
4264
4265 int slsi_mlme_install_apf_request(struct slsi_dev *sdev, struct net_device *dev,
4266 u8 *program, u32 program_len)
4267 {
4268 struct netdev_vif *ndev_vif = netdev_priv(dev);
4269 struct sk_buff *req;
4270 struct sk_buff *rx;
4271 int r = 0;
4272
4273 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
4274
4275 if (!ndev_vif->activated) {
4276 SLSI_ERR(sdev, "ndev_vif is not activated\n");
4277 r = -EINVAL;
4278 goto exit;
4279 }
4280
4281 if (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) {
4282 SLSI_ERR(sdev, "vif_type is not FAPI_VIFTYPE_STATION\n");
4283 r = -EINVAL;
4284 goto exit;
4285 }
4286
4287 req = fapi_alloc(mlme_install_apf_req, MLME_INSTALL_APF_REQ, ndev_vif->ifnum, program_len);
4288 if (!req) {
4289 r = -ENOMEM;
4290 goto exit;
4291 }
4292
4293 /* filter_mode will be "don't care" for FW */
4294 fapi_set_u16(req, u.mlme_install_apf_req.filter_mode, FAPI_APFFILTERMODE_SUSPEND);
4295 fapi_append_data(req, program, program_len);
4296
4297 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_install_apf_req(vif:%u, filter_mode:%d)\n",
4298 ndev_vif->ifnum, FAPI_APFFILTERMODE_SUSPEND);
4299 rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_INSTALL_APF_CFM);
4300 if (!rx) {
4301 r = -EIO;
4302 goto exit;
4303 }
4304
4305 if (fapi_get_u16(rx, u.mlme_install_apf_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4306 SLSI_NET_ERR(dev, "mlme_install_apf_cfm(result:0x%04x) ERROR\n",
4307 fapi_get_u16(rx, u.mlme_install_apf_cfm.result_code));
4308 r = -EINVAL;
4309 }
4310
4311 exit:
4312 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
4313 return r;
4314 }
4315
4316 #ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
4317 int slsi_mlme_arp_detect_request(struct slsi_dev *sdev, struct net_device *dev, u16 action, u8 *target_ipaddr)
4318 {
4319 struct netdev_vif *ndev_vif = netdev_priv(dev);
4320 struct sk_buff *req;
4321 struct sk_buff *rx;
4322 int r = 0;
4323 u32 ipaddress = 0x0;
4324 int i = 0;
4325
4326 if (!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex)) {
4327 SLSI_ERR(sdev, "ndev_vif mutex is not locked\n");
4328 r = -EINVAL;
4329 goto exit;
4330 }
4331
4332 if (!ndev_vif->activated) {
4333 SLSI_ERR(sdev, "ndev_vif is not activated\n");
4334 r = -EINVAL;
4335 goto exit;
4336 }
4337
4338 if ((ndev_vif->vif_type != FAPI_VIFTYPE_STATION) && (ndev_vif->iftype == NL80211_IFTYPE_STATION)) {
4339 SLSI_ERR(sdev, "vif_type is not FAPI_VIFTYPE_STATION\n");
4340 r = -EINVAL;
4341 goto exit;
4342 }
4343
4344 req = fapi_alloc(mlme_arp_detect_req, MLME_ARP_DETECT_REQ, ndev_vif->ifnum, 0);
4345 if (!req) {
4346 r = -ENOMEM;
4347 goto exit;
4348 }
4349
4350 for (i = 0; i < 4; i++)
4351 ipaddress = (ipaddress << 8) | ((unsigned char)target_ipaddr[i]);
4352 ipaddress = htonl(ipaddress);
4353
4354 fapi_set_u16(req, u.mlme_arp_detect_req.arp_detect_action, action);
4355 fapi_append_data(req, (const u8 *)&ipaddress, 4);
4356
4357 SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_arp_detect_req(vif:%u, action:%d IP Address:%d.%d.%d.%d)\n",
4358 ndev_vif->ifnum, action, ndev_vif->target_ip_addr[0], ndev_vif->target_ip_addr[1],
4359 ndev_vif->target_ip_addr[2], ndev_vif->target_ip_addr[3]);
4360 rx = slsi_mlme_req_cfm(sdev, dev, req, MLME_ARP_DETECT_CFM);
4361 if (!rx) {
4362 r = -EIO;
4363 goto exit;
4364 }
4365
4366 if (fapi_get_u16(rx, u.mlme_arp_detect_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4367 SLSI_NET_ERR(dev, "mlme_arp_detect_cfm(result:0x%04x) ERROR\n",
4368 fapi_get_u16(rx, u.mlme_arp_detect_cfm.result_code));
4369 r = -EINVAL;
4370 }
4371
4372 exit:
4373 return r;
4374 }
4375 #endif
4376
4377 #ifdef CONFIG_SCSC_WLAN_DEBUG
4378 #define SLSI_TEST_CONFIG_MONITOR_MODE_DESCRIPTOR_SIZE (12)
4379 int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_chan_def *chandef)
4380 {
4381 struct netdev_vif *ndev_vif = netdev_priv(dev);
4382 struct sk_buff *req;
4383 struct sk_buff *cfm;
4384 u8 *p = NULL;
4385 size_t alloc_data_size = 0;
4386 u16 center_freq1;
4387 u16 center_freq2;
4388 u16 chan_info;
4389 int r = 0;
4390
4391 const u8 monitor_config_ie_header[] = {
4392 0xDD, /* Element ID: Vendor Specific */
4393 0x11, /* Length */
4394 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
4395 0x10, /* OUI Type: Monitor mode parameters */
4396 0x01 /* OUI Subtype: configuration */
4397 };
4398
4399 if (slsi_is_test_mode_enabled()) {
4400 SLSI_NET_WARN(dev, "WlanLite: NOT supported\n");
4401 return -EOPNOTSUPP;
4402 }
4403
4404 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
4405
4406 chan_info = slsi_get_chann_info(sdev, chandef);
4407 SLSI_NET_DBG2(dev, SLSI_MLME, "test_configure_monitor_mode_req(center_freq1:%u, chan_info:%u, center_freq2:%u)\n",
4408 chandef->center_freq1,
4409 chan_info,
4410 chandef->center_freq2);
4411
4412 center_freq1 = SLSI_FREQ_HOST_TO_FW(chandef->center_freq1);
4413 center_freq1 = cpu_to_le16(center_freq1);
4414 center_freq2 = SLSI_FREQ_HOST_TO_FW(chandef->center_freq2);
4415 center_freq2 = cpu_to_le16(center_freq2);
4416
4417 alloc_data_size = sizeof(monitor_config_ie_header) + SLSI_TEST_CONFIG_MONITOR_MODE_DESCRIPTOR_SIZE;
4418
4419 req = fapi_alloc(test_configure_monitor_mode_req, TEST_CONFIGURE_MONITOR_MODE_REQ, ndev_vif->ifnum, alloc_data_size);
4420 if (!req) {
4421 SLSI_NET_ERR(dev, "failed to alloc Monitor mode request (len:%d)\n", alloc_data_size);
4422 return -ENOMEM;
4423 }
4424
4425 fapi_append_data(req, monitor_config_ie_header, sizeof(monitor_config_ie_header));
4426 fapi_append_data(req, (const u8 *)&center_freq1, 2);
4427 fapi_append_data(req, (const u8 *)&chan_info, 2);
4428 p = fapi_append_data(req, (const u8 *)&center_freq2, 2);
4429
4430 /* MAC address filtering is not supported yet; so fill in zeros */
4431 memset(p, 0, 6);
4432
4433 cfm = slsi_mlme_req_cfm(sdev, dev, req, TEST_CONFIGURE_MONITOR_MODE_CFM);
4434 if (!cfm) {
4435 SLSI_NET_ERR(dev, "failed to receive Confirm\n");
4436 return -EIO;
4437 }
4438
4439 if (fapi_get_u16(cfm, u.mlme_set_channel_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4440 SLSI_NET_ERR(dev, "test_configure_monitor_mode_cfm(result:0x%04x) ERROR\n",
4441 fapi_get_u16(cfm, u.test_configure_monitor_mode_cfm.result_code));
4442 r = -EINVAL;
4443 }
4444
4445 slsi_kfree_skb(cfm);
4446 return r;
4447 }
4448 #endif
4449
4450 int slsi_mlme_set_country(struct slsi_dev *sdev, char *alpha2)
4451 {
4452 struct slsi_mib_data mib_data = { 0, NULL };
4453 struct sk_buff *req;
4454 struct sk_buff *cfm;
4455 int country_index = 0;
4456 u32 rules_len = 0;
4457 u16 country_code = 0;
4458 u8 append_byte = 0;
4459 u8 dfs_region = 0;
4460 int i = 0;
4461 int error = 0;
4462
4463 if (sdev->regdb.regdb_state == SLSI_REG_DB_SET) {
4464 for (i = 0; i < sdev->regdb.num_countries; i++) {
4465 if ((sdev->regdb.country[i].alpha2[0] == alpha2[0]) && (sdev->regdb.country[i].alpha2[1] == alpha2[1])) {
4466 country_index = i;
4467 break;
4468 }
4469 }
4470
4471 /* 7 octets for each rule */
4472 rules_len = 7 * sdev->regdb.country[country_index].collection->reg_rule_num;
4473 dfs_region = sdev->regdb.country[country_index].dfs_region;
4474 }
4475
4476 /* last parameter should be length of bulk data */
4477 req = fapi_alloc(mlme_set_country_req, MLME_SET_COUNTRY_REQ, 0, rules_len);
4478 if (!req)
4479 return -ENOMEM;
4480
4481 country_code = (((u16)alpha2[0] << 8) | (u16)alpha2[1]);
4482 fapi_set_u16(req, u.mlme_set_country_req.country_code, country_code);
4483 fapi_set_u16(req, u.mlme_set_country_req.dfs_regulatory_domain, dfs_region);
4484 if (rules_len) {
4485 for (i = 0; i < sdev->regdb.country[country_index].collection->reg_rule_num; i++) {
4486 append_byte = (sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->start_freq * 2) & 0xFF;
4487 fapi_append_data(req, &append_byte, 1);
4488 append_byte = ((sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->start_freq * 2) >> 8) & 0xFF;
4489 fapi_append_data(req, &append_byte, 1);
4490 append_byte = (sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->end_freq * 2) & 0xFF;
4491 fapi_append_data(req, &append_byte, 1);
4492 append_byte = ((sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->end_freq * 2) >> 8) & 0xFF;
4493 fapi_append_data(req, &append_byte, 1);
4494 append_byte = sdev->regdb.country[country_index].collection->reg_rule[i]->freq_range->max_bandwidth & 0xFF;
4495 fapi_append_data(req, &append_byte, 1);
4496 append_byte = sdev->regdb.country[country_index].collection->reg_rule[i]->max_eirp & 0xFF;
4497 fapi_append_data(req, &append_byte, 1);
4498 append_byte = sdev->regdb.country[country_index].collection->reg_rule[i]->flags & 0xFF;
4499 fapi_append_data(req, &append_byte, 1);
4500 }
4501 }
4502
4503 SLSI_DBG2(sdev, SLSI_MLME, "mlme_set_country_req(country:%c%c, dfs_regulatory_domain:%x)\n", alpha2[0], alpha2[1], dfs_region);
4504 cfm = slsi_mlme_req_cfm(sdev, NULL, req, MLME_SET_COUNTRY_CFM);
4505 if (!cfm)
4506 return -EIO;
4507
4508 if (fapi_get_u16(cfm, u.mlme_set_country_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
4509 SLSI_ERR(sdev, "mlme_set_country_cfm(result:0x%04x) ERROR\n",
4510 fapi_get_u16(cfm, u.mlme_set_country_cfm.result_code));
4511 slsi_kfree_skb(cfm);
4512 error = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_DEFAULT_COUNTRY, 3, alpha2, 0);
4513 if (error != SLSI_MIB_STATUS_SUCCESS)
4514 return -ENOMEM;
4515
4516 if (WARN_ON(mib_data.dataLength == 0))
4517 return -EINVAL;
4518
4519 error = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength);
4520 if (error)
4521 return -EINVAL;
4522
4523 kfree(mib_data.data);
4524 return 0;
4525 }
4526
4527 slsi_kfree_skb(cfm);
4528 return 0;
4529 }
4530
4531 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
4532 void slsi_mlme_set_country_for_recovery(struct slsi_dev *sdev)
4533 {
4534 int ret = 0;
4535 struct slsi_mib_data mib_data = { 0, NULL };
4536
4537 SLSI_MUTEX_LOCK(sdev->device_config_mutex);
4538 ret = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_DEFAULT_COUNTRY, 3, sdev->device_config.domain_info.regdomain->alpha2, 0);
4539 if (ret != SLSI_MIB_STATUS_SUCCESS) {
4540 ret = -ENOMEM;
4541 SLSI_ERR(sdev, "Err setting country error = %d\n", ret);
4542 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
4543 return ;
4544 }
4545
4546 if (mib_data.dataLength == 0) {
4547 ret = -EINVAL;
4548 SLSI_ERR(sdev, "Err setting country error = %d\n", ret);
4549 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
4550 return ;
4551 }
4552
4553 ret = slsi_mlme_set(sdev, NULL, mib_data.data, mib_data.dataLength);
4554 kfree(mib_data.data);
4555
4556 if (ret)
4557 SLSI_ERR(sdev, "Err setting country error = %d\n", ret);
4558 SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
4559 }
4560 #endif