aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex/scan.c
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2011-08-10 21:53:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-12 13:45:05 -0400
commit7c6fa2a843c5ac0f8e3e4bf679cee9c93d5e3437 (patch)
tree360b31141b176026c64631fc0a7a21c4aa3ea258 /drivers/net/wireless/mwifiex/scan.c
parent9af73cf7f356801e6e5837eb338d197de5c8f37c (diff)
mwifiex: use cfg80211 dynamic scan table and cfg80211_get_bss API
Instead of maintaining static scan table in driver, scan list is sent to cfg80211 stack (after parsing each scan command response). In assoc handler (for infra and ibss network) requested BSS information is retrieved using cfg80211_get_bss() API. With the changes above some redundant code are removed. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwifiex/scan.c')
-rw-r--r--drivers/net/wireless/mwifiex/scan.c1576
1 files changed, 299 insertions, 1277 deletions
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 1fdfd41c3100..b28241c6e737 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -172,36 +172,6 @@ mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
172} 172}
173 173
174/* 174/*
175 * Sends IOCTL request to get the best BSS.
176 *
177 * This function allocates the IOCTL request buffer, fills it
178 * with requisite parameters and calls the IOCTL handler.
179 */
180int mwifiex_find_best_bss(struct mwifiex_private *priv,
181 struct mwifiex_ssid_bssid *ssid_bssid)
182{
183 struct mwifiex_ssid_bssid tmp_ssid_bssid;
184 u8 *mac;
185
186 if (!ssid_bssid)
187 return -1;
188
189 memcpy(&tmp_ssid_bssid, ssid_bssid,
190 sizeof(struct mwifiex_ssid_bssid));
191
192 if (!mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid)) {
193 memcpy(ssid_bssid, &tmp_ssid_bssid,
194 sizeof(struct mwifiex_ssid_bssid));
195 mac = (u8 *) &ssid_bssid->bssid;
196 dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s,"
197 " %pM\n", ssid_bssid->ssid.ssid, mac);
198 return 0;
199 }
200
201 return -1;
202}
203
204/*
205 * Sends IOCTL request to start a scan with user configurations. 175 * Sends IOCTL request to start a scan with user configurations.
206 * 176 *
207 * This function allocates the IOCTL request buffer, fills it 177 * This function allocates the IOCTL request buffer, fills it
@@ -286,8 +256,7 @@ mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv,
286 */ 256 */
287static bool 257static bool
288mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv, 258mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
289 struct mwifiex_bssdescriptor *bss_desc, 259 struct mwifiex_bssdescriptor *bss_desc)
290 int index)
291{ 260{
292 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED 261 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
293 && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled 262 && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
@@ -298,9 +267,9 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
298 * LinkSys WRT54G && bss_desc->privacy 267 * LinkSys WRT54G && bss_desc->privacy
299 */ 268 */
300 ) { 269 ) {
301 dev_dbg(priv->adapter->dev, "info: %s: WPA: index=%d" 270 dev_dbg(priv->adapter->dev, "info: %s: WPA:"
302 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " 271 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
303 "EncMode=%#x privacy=%#x\n", __func__, index, 272 "EncMode=%#x privacy=%#x\n", __func__,
304 (bss_desc->bcn_wpa_ie) ? 273 (bss_desc->bcn_wpa_ie) ?
305 (*(bss_desc->bcn_wpa_ie)). 274 (*(bss_desc->bcn_wpa_ie)).
306 vend_hdr.element_id : 0, 275 vend_hdr.element_id : 0,
@@ -324,8 +293,7 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
324 */ 293 */
325static bool 294static bool
326mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv, 295mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
327 struct mwifiex_bssdescriptor *bss_desc, 296 struct mwifiex_bssdescriptor *bss_desc)
328 int index)
329{ 297{
330 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED 298 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
331 && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled 299 && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled
@@ -336,9 +304,9 @@ mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
336 * LinkSys WRT54G && bss_desc->privacy 304 * LinkSys WRT54G && bss_desc->privacy
337 */ 305 */
338 ) { 306 ) {
339 dev_dbg(priv->adapter->dev, "info: %s: WPA2: index=%d" 307 dev_dbg(priv->adapter->dev, "info: %s: WPA2: "
340 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " 308 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
341 "EncMode=%#x privacy=%#x\n", __func__, index, 309 "EncMode=%#x privacy=%#x\n", __func__,
342 (bss_desc->bcn_wpa_ie) ? 310 (bss_desc->bcn_wpa_ie) ?
343 (*(bss_desc->bcn_wpa_ie)). 311 (*(bss_desc->bcn_wpa_ie)).
344 vend_hdr.element_id : 0, 312 vend_hdr.element_id : 0,
@@ -383,8 +351,7 @@ mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv,
383 */ 351 */
384static bool 352static bool
385mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv, 353mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
386 struct mwifiex_bssdescriptor *bss_desc, 354 struct mwifiex_bssdescriptor *bss_desc)
387 int index)
388{ 355{
389 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED 356 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
390 && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled 357 && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
@@ -395,9 +362,9 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
395 && priv->sec_info.encryption_mode 362 && priv->sec_info.encryption_mode
396 && bss_desc->privacy) { 363 && bss_desc->privacy) {
397 dev_dbg(priv->adapter->dev, "info: %s: dynamic " 364 dev_dbg(priv->adapter->dev, "info: %s: dynamic "
398 "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x " 365 "WEP: wpa_ie=%#x wpa2_ie=%#x "
399 "EncMode=%#x privacy=%#x\n", 366 "EncMode=%#x privacy=%#x\n",
400 __func__, index, 367 __func__,
401 (bss_desc->bcn_wpa_ie) ? 368 (bss_desc->bcn_wpa_ie) ?
402 (*(bss_desc->bcn_wpa_ie)). 369 (*(bss_desc->bcn_wpa_ie)).
403 vend_hdr.element_id : 0, 370 vend_hdr.element_id : 0,
@@ -430,42 +397,41 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
430 * Compatibility is not matched while roaming, except for mode. 397 * Compatibility is not matched while roaming, except for mode.
431 */ 398 */
432static s32 399static s32
433mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode) 400mwifiex_is_network_compatible(struct mwifiex_private *priv,
401 struct mwifiex_bssdescriptor *bss_desc, u32 mode)
434{ 402{
435 struct mwifiex_adapter *adapter = priv->adapter; 403 struct mwifiex_adapter *adapter = priv->adapter;
436 struct mwifiex_bssdescriptor *bss_desc;
437 404
438 bss_desc = &adapter->scan_table[index];
439 bss_desc->disable_11n = false; 405 bss_desc->disable_11n = false;
440 406
441 /* Don't check for compatibility if roaming */ 407 /* Don't check for compatibility if roaming */
442 if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION) 408 if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION)
443 && (bss_desc->bss_mode == NL80211_IFTYPE_STATION)) 409 && (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
444 return index; 410 return 0;
445 411
446 if (priv->wps.session_enable) { 412 if (priv->wps.session_enable) {
447 dev_dbg(adapter->dev, 413 dev_dbg(adapter->dev,
448 "info: return success directly in WPS period\n"); 414 "info: return success directly in WPS period\n");
449 return index; 415 return 0;
450 } 416 }
451 417
452 if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) { 418 if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) {
453 dev_dbg(adapter->dev, "info: return success for WAPI AP\n"); 419 dev_dbg(adapter->dev, "info: return success for WAPI AP\n");
454 return index; 420 return 0;
455 } 421 }
456 422
457 if (bss_desc->bss_mode == mode) { 423 if (bss_desc->bss_mode == mode) {
458 if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) { 424 if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) {
459 /* No security */ 425 /* No security */
460 return index; 426 return 0;
461 } else if (mwifiex_is_network_compatible_for_static_wep(priv, 427 } else if (mwifiex_is_network_compatible_for_static_wep(priv,
462 bss_desc)) { 428 bss_desc)) {
463 /* Static WEP enabled */ 429 /* Static WEP enabled */
464 dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n"); 430 dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n");
465 bss_desc->disable_11n = true; 431 bss_desc->disable_11n = true;
466 return index; 432 return 0;
467 } else if (mwifiex_is_network_compatible_for_wpa(priv, bss_desc, 433 } else if (mwifiex_is_network_compatible_for_wpa(priv,
468 index)) { 434 bss_desc)) {
469 /* WPA enabled */ 435 /* WPA enabled */
470 if (((priv->adapter->config_bands & BAND_GN 436 if (((priv->adapter->config_bands & BAND_GN
471 || priv->adapter->config_bands & BAND_AN) 437 || priv->adapter->config_bands & BAND_AN)
@@ -483,9 +449,9 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
483 return -1; 449 return -1;
484 } 450 }
485 } 451 }
486 return index; 452 return 0;
487 } else if (mwifiex_is_network_compatible_for_wpa2(priv, 453 } else if (mwifiex_is_network_compatible_for_wpa2(priv,
488 bss_desc, index)) { 454 bss_desc)) {
489 /* WPA2 enabled */ 455 /* WPA2 enabled */
490 if (((priv->adapter->config_bands & BAND_GN 456 if (((priv->adapter->config_bands & BAND_GN
491 || priv->adapter->config_bands & BAND_AN) 457 || priv->adapter->config_bands & BAND_AN)
@@ -503,22 +469,22 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
503 return -1; 469 return -1;
504 } 470 }
505 } 471 }
506 return index; 472 return 0;
507 } else if (mwifiex_is_network_compatible_for_adhoc_aes(priv, 473 } else if (mwifiex_is_network_compatible_for_adhoc_aes(priv,
508 bss_desc)) { 474 bss_desc)) {
509 /* Ad-hoc AES enabled */ 475 /* Ad-hoc AES enabled */
510 return index; 476 return 0;
511 } else if (mwifiex_is_network_compatible_for_dynamic_wep(priv, 477 } else if (mwifiex_is_network_compatible_for_dynamic_wep(priv,
512 bss_desc, index)) { 478 bss_desc)) {
513 /* Dynamic WEP enabled */ 479 /* Dynamic WEP enabled */
514 return index; 480 return 0;
515 } 481 }
516 482
517 /* Security doesn't match */ 483 /* Security doesn't match */
518 dev_dbg(adapter->dev, "info: %s: failed: index=%d " 484 dev_dbg(adapter->dev, "info: %s: failed: "
519 "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode" 485 "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode"
520 "=%#x privacy=%#x\n", 486 "=%#x privacy=%#x\n",
521 __func__, index, 487 __func__,
522 (bss_desc->bcn_wpa_ie) ? 488 (bss_desc->bcn_wpa_ie) ?
523 (*(bss_desc->bcn_wpa_ie)).vend_hdr. 489 (*(bss_desc->bcn_wpa_ie)).vend_hdr.
524 element_id : 0, 490 element_id : 0,
@@ -538,52 +504,6 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
538} 504}
539 505
540/* 506/*
541 * This function finds the best SSID in the scan list.
542 *
543 * It searches the scan table for the best SSID that also matches the current
544 * adapter network preference (mode, security etc.).
545 */
546static s32
547mwifiex_find_best_network_in_list(struct mwifiex_private *priv)
548{
549 struct mwifiex_adapter *adapter = priv->adapter;
550 u32 mode = priv->bss_mode;
551 s32 best_net = -1;
552 s32 best_rssi = 0;
553 u32 i;
554
555 dev_dbg(adapter->dev, "info: num of BSSIDs = %d\n",
556 adapter->num_in_scan_table);
557
558 for (i = 0; i < adapter->num_in_scan_table; i++) {
559 switch (mode) {
560 case NL80211_IFTYPE_STATION:
561 case NL80211_IFTYPE_ADHOC:
562 if (mwifiex_is_network_compatible(priv, i, mode) >= 0) {
563 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
564 best_rssi) {
565 best_rssi = SCAN_RSSI(adapter->
566 scan_table[i].rssi);
567 best_net = i;
568 }
569 }
570 break;
571 case NL80211_IFTYPE_UNSPECIFIED:
572 default:
573 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
574 best_rssi) {
575 best_rssi = SCAN_RSSI(adapter->scan_table[i].
576 rssi);
577 best_net = i;
578 }
579 break;
580 }
581 }
582
583 return best_net;
584}
585
586/*
587 * This function creates a channel list for the driver to scan, based 507 * This function creates a channel list for the driver to scan, based
588 * on region/band information. 508 * on region/band information.
589 * 509 *
@@ -1161,34 +1081,13 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
1161} 1081}
1162 1082
1163/* 1083/*
1164 * This function interprets a BSS scan response returned from the firmware. 1084 * This function parses provided beacon buffer and updates
1165 * 1085 * respective fields in bss descriptor structure.
1166 * The various fixed fields and IEs are parsed and passed back for a BSS
1167 * probe response or beacon from scan command. Information is recorded as
1168 * needed in the scan table for that entry.
1169 *
1170 * The following IE types are recognized and parsed -
1171 * - SSID
1172 * - Supported rates
1173 * - FH parameters set
1174 * - DS parameters set
1175 * - CF parameters set
1176 * - IBSS parameters set
1177 * - ERP information
1178 * - Extended supported rates
1179 * - Vendor specific (221)
1180 * - RSN IE
1181 * - WAPI IE
1182 * - HT capability
1183 * - HT operation
1184 * - BSS Coexistence 20/40
1185 * - Extended capability
1186 * - Overlapping BSS scan parameters
1187 */ 1086 */
1188static int 1087int
1189mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter, 1088mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1190 struct mwifiex_bssdescriptor *bss_entry, 1089 struct mwifiex_bssdescriptor *bss_entry,
1191 u8 **beacon_info, u32 *bytes_left) 1090 u8 *ie_buf, u32 ie_len)
1192{ 1091{
1193 int ret = 0; 1092 int ret = 0;
1194 u8 element_id; 1093 u8 element_id;
@@ -1196,135 +1095,43 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1196 struct ieee_types_ds_param_set *ds_param_set; 1095 struct ieee_types_ds_param_set *ds_param_set;
1197 struct ieee_types_cf_param_set *cf_param_set; 1096 struct ieee_types_cf_param_set *cf_param_set;
1198 struct ieee_types_ibss_param_set *ibss_param_set; 1097 struct ieee_types_ibss_param_set *ibss_param_set;
1199 __le16 beacon_interval;
1200 __le16 capabilities;
1201 u8 *current_ptr; 1098 u8 *current_ptr;
1202 u8 *rate; 1099 u8 *rate;
1203 u8 element_len; 1100 u8 element_len;
1204 u16 total_ie_len; 1101 u16 total_ie_len;
1205 u8 bytes_to_copy; 1102 u8 bytes_to_copy;
1206 u8 rate_size; 1103 u8 rate_size;
1207 u16 beacon_size;
1208 u8 found_data_rate_ie; 1104 u8 found_data_rate_ie;
1209 u32 bytes_left_for_current_beacon; 1105 u32 bytes_left;
1210 struct ieee_types_vendor_specific *vendor_ie; 1106 struct ieee_types_vendor_specific *vendor_ie;
1211 const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; 1107 const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1212 const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; 1108 const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1213 1109
1214 found_data_rate_ie = false; 1110 found_data_rate_ie = false;
1215 rate_size = 0; 1111 rate_size = 0;
1216 beacon_size = 0; 1112 current_ptr = ie_buf;
1217 1113 bytes_left = ie_len;
1218 if (*bytes_left >= sizeof(beacon_size)) { 1114 bss_entry->beacon_buf = ie_buf;
1219 /* Extract & convert beacon size from the command buffer */ 1115 bss_entry->beacon_buf_size = ie_len;
1220 memcpy(&beacon_size, *beacon_info, sizeof(beacon_size));
1221 *bytes_left -= sizeof(beacon_size);
1222 *beacon_info += sizeof(beacon_size);
1223 }
1224
1225 if (!beacon_size || beacon_size > *bytes_left) {
1226 *beacon_info += *bytes_left;
1227 *bytes_left = 0;
1228 return -1;
1229 }
1230
1231 /* Initialize the current working beacon pointer for this BSS
1232 iteration */
1233 current_ptr = *beacon_info;
1234
1235 /* Advance the return beacon pointer past the current beacon */
1236 *beacon_info += beacon_size;
1237 *bytes_left -= beacon_size;
1238
1239 bytes_left_for_current_beacon = beacon_size;
1240
1241 memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN);
1242 dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n",
1243 bss_entry->mac_address);
1244
1245 current_ptr += ETH_ALEN;
1246 bytes_left_for_current_beacon -= ETH_ALEN;
1247
1248 if (bytes_left_for_current_beacon < 12) {
1249 dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
1250 return -1;
1251 }
1252
1253 /*
1254 * Next 4 fields are RSSI, time stamp, beacon interval,
1255 * and capability information
1256 */
1257
1258 /* RSSI is 1 byte long */
1259 bss_entry->rssi = (s32) (*current_ptr);
1260 dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr);
1261 current_ptr += 1;
1262 bytes_left_for_current_beacon -= 1;
1263
1264 /*
1265 * The RSSI is not part of the beacon/probe response. After we have
1266 * advanced current_ptr past the RSSI field, save the remaining
1267 * data for use at the application layer
1268 */
1269 bss_entry->beacon_buf = current_ptr;
1270 bss_entry->beacon_buf_size = bytes_left_for_current_beacon;
1271
1272 /* Time stamp is 8 bytes long */
1273 memcpy(bss_entry->time_stamp, current_ptr, 8);
1274 current_ptr += 8;
1275 bytes_left_for_current_beacon -= 8;
1276
1277 /* Beacon interval is 2 bytes long */
1278 memcpy(&beacon_interval, current_ptr, 2);
1279 bss_entry->beacon_period = le16_to_cpu(beacon_interval);
1280 current_ptr += 2;
1281 bytes_left_for_current_beacon -= 2;
1282
1283 /* Capability information is 2 bytes long */
1284 memcpy(&capabilities, current_ptr, 2);
1285 dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
1286 capabilities);
1287 bss_entry->cap_info_bitmap = le16_to_cpu(capabilities);
1288 current_ptr += 2;
1289 bytes_left_for_current_beacon -= 2;
1290
1291 /* Rest of the current buffer are IE's */
1292 dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n",
1293 bytes_left_for_current_beacon);
1294
1295 if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
1296 dev_dbg(adapter->dev, "info: InterpretIE: AP WEP enabled\n");
1297 bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
1298 } else {
1299 bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
1300 }
1301
1302 if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
1303 bss_entry->bss_mode = NL80211_IFTYPE_ADHOC;
1304 else
1305 bss_entry->bss_mode = NL80211_IFTYPE_STATION;
1306
1307 1116
1308 /* Process variable IE */ 1117 /* Process variable IE */
1309 while (bytes_left_for_current_beacon >= 2) { 1118 while (bytes_left >= 2) {
1310 element_id = *current_ptr; 1119 element_id = *current_ptr;
1311 element_len = *(current_ptr + 1); 1120 element_len = *(current_ptr + 1);
1312 total_ie_len = element_len + sizeof(struct ieee_types_header); 1121 total_ie_len = element_len + sizeof(struct ieee_types_header);
1313 1122
1314 if (bytes_left_for_current_beacon < total_ie_len) { 1123 if (bytes_left < total_ie_len) {
1315 dev_err(adapter->dev, "err: InterpretIE: in processing" 1124 dev_err(adapter->dev, "err: InterpretIE: in processing"
1316 " IE, bytes left < IE length\n"); 1125 " IE, bytes left < IE length\n");
1317 bytes_left_for_current_beacon = 0; 1126 return -1;
1318 ret = -1;
1319 continue;
1320 } 1127 }
1321 switch (element_id) { 1128 switch (element_id) {
1322 case WLAN_EID_SSID: 1129 case WLAN_EID_SSID:
1323 bss_entry->ssid.ssid_len = element_len; 1130 bss_entry->ssid.ssid_len = element_len;
1324 memcpy(bss_entry->ssid.ssid, (current_ptr + 2), 1131 memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1325 element_len); 1132 element_len);
1326 dev_dbg(adapter->dev, "info: InterpretIE: ssid: %-32s\n", 1133 dev_dbg(adapter->dev, "info: InterpretIE: ssid: "
1327 bss_entry->ssid.ssid); 1134 "%-32s\n", bss_entry->ssid.ssid);
1328 break; 1135 break;
1329 1136
1330 case WLAN_EID_SUPP_RATES: 1137 case WLAN_EID_SUPP_RATES:
@@ -1471,13 +1278,6 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1471 sizeof(struct ieee_types_header) - 1278 sizeof(struct ieee_types_header) -
1472 bss_entry->beacon_buf); 1279 bss_entry->beacon_buf);
1473 break; 1280 break;
1474 case WLAN_EID_OVERLAP_BSS_SCAN_PARAM:
1475 bss_entry->bcn_obss_scan =
1476 (struct ieee_types_obss_scan_param *)
1477 current_ptr;
1478 bss_entry->overlap_bss_offset = (u16) (current_ptr -
1479 bss_entry->beacon_buf);
1480 break;
1481 default: 1281 default:
1482 break; 1282 break;
1483 } 1283 }
@@ -1485,577 +1285,13 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1485 current_ptr += element_len + 2; 1285 current_ptr += element_len + 2;
1486 1286
1487 /* Need to account for IE ID and IE Len */ 1287 /* Need to account for IE ID and IE Len */
1488 bytes_left_for_current_beacon -= (element_len + 2); 1288 bytes_left -= (element_len + 2);
1489 1289
1490 } /* while (bytes_left_for_current_beacon > 2) */ 1290 } /* while (bytes_left > 2) */
1491 return ret; 1291 return ret;
1492} 1292}
1493 1293
1494/* 1294/*
1495 * This function adjusts the pointers used in beacon buffers to reflect
1496 * shifts.
1497 *
1498 * The memory allocated for beacon buffers is of fixed sizes where all the
1499 * saved beacons must be stored. New beacons are added in the free portion
1500 * of this memory, space permitting; while duplicate beacon buffers are
1501 * placed at the same start location. However, since duplicate beacon
1502 * buffers may not match the size of the old one, all the following buffers
1503 * in the memory must be shifted to either make space, or to fill up freed
1504 * up space.
1505 *
1506 * This function is used to update the beacon buffer pointers that are past
1507 * an existing beacon buffer that is updated with a new one of different
1508 * size. The pointers are shifted by a fixed amount, either forward or
1509 * backward.
1510 *
1511 * the following pointers in every affected beacon buffers are changed, if
1512 * present -
1513 * - WPA IE pointer
1514 * - RSN IE pointer
1515 * - WAPI IE pointer
1516 * - HT capability IE pointer
1517 * - HT information IE pointer
1518 * - BSS coexistence 20/40 IE pointer
1519 * - Extended capability IE pointer
1520 * - Overlapping BSS scan parameter IE pointer
1521 */
1522static void
1523mwifiex_adjust_beacon_buffer_ptrs(struct mwifiex_private *priv, u8 advance,
1524 u8 *bcn_store, u32 rem_bcn_size,
1525 u32 num_of_ent)
1526{
1527 struct mwifiex_adapter *adapter = priv->adapter;
1528 u32 adj_idx;
1529 for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) {
1530 if (adapter->scan_table[adj_idx].beacon_buf > bcn_store) {
1531
1532 if (advance)
1533 adapter->scan_table[adj_idx].beacon_buf +=
1534 rem_bcn_size;
1535 else
1536 adapter->scan_table[adj_idx].beacon_buf -=
1537 rem_bcn_size;
1538
1539 if (adapter->scan_table[adj_idx].bcn_wpa_ie)
1540 adapter->scan_table[adj_idx].bcn_wpa_ie =
1541 (struct ieee_types_vendor_specific *)
1542 (adapter->scan_table[adj_idx].beacon_buf +
1543 adapter->scan_table[adj_idx].wpa_offset);
1544 if (adapter->scan_table[adj_idx].bcn_rsn_ie)
1545 adapter->scan_table[adj_idx].bcn_rsn_ie =
1546 (struct ieee_types_generic *)
1547 (adapter->scan_table[adj_idx].beacon_buf +
1548 adapter->scan_table[adj_idx].rsn_offset);
1549 if (adapter->scan_table[adj_idx].bcn_wapi_ie)
1550 adapter->scan_table[adj_idx].bcn_wapi_ie =
1551 (struct ieee_types_generic *)
1552 (adapter->scan_table[adj_idx].beacon_buf +
1553 adapter->scan_table[adj_idx].wapi_offset);
1554 if (adapter->scan_table[adj_idx].bcn_ht_cap)
1555 adapter->scan_table[adj_idx].bcn_ht_cap =
1556 (struct ieee80211_ht_cap *)
1557 (adapter->scan_table[adj_idx].beacon_buf +
1558 adapter->scan_table[adj_idx].ht_cap_offset);
1559
1560 if (adapter->scan_table[adj_idx].bcn_ht_info)
1561 adapter->scan_table[adj_idx].bcn_ht_info =
1562 (struct ieee80211_ht_info *)
1563 (adapter->scan_table[adj_idx].beacon_buf +
1564 adapter->scan_table[adj_idx].ht_info_offset);
1565 if (adapter->scan_table[adj_idx].bcn_bss_co_2040)
1566 adapter->scan_table[adj_idx].bcn_bss_co_2040 =
1567 (u8 *)
1568 (adapter->scan_table[adj_idx].beacon_buf +
1569 adapter->scan_table[adj_idx].bss_co_2040_offset);
1570 if (adapter->scan_table[adj_idx].bcn_ext_cap)
1571 adapter->scan_table[adj_idx].bcn_ext_cap =
1572 (u8 *)
1573 (adapter->scan_table[adj_idx].beacon_buf +
1574 adapter->scan_table[adj_idx].ext_cap_offset);
1575 if (adapter->scan_table[adj_idx].bcn_obss_scan)
1576 adapter->scan_table[adj_idx].bcn_obss_scan =
1577 (struct ieee_types_obss_scan_param *)
1578 (adapter->scan_table[adj_idx].beacon_buf +
1579 adapter->scan_table[adj_idx].overlap_bss_offset);
1580 }
1581 }
1582}
1583
1584/*
1585 * This function updates the pointers used in beacon buffer for given bss
1586 * descriptor to reflect shifts
1587 *
1588 * Following pointers are updated
1589 * - WPA IE pointer
1590 * - RSN IE pointer
1591 * - WAPI IE pointer
1592 * - HT capability IE pointer
1593 * - HT information IE pointer
1594 * - BSS coexistence 20/40 IE pointer
1595 * - Extended capability IE pointer
1596 * - Overlapping BSS scan parameter IE pointer
1597 */
1598static void
1599mwifiex_update_beacon_buffer_ptrs(struct mwifiex_bssdescriptor *beacon)
1600{
1601 if (beacon->bcn_wpa_ie)
1602 beacon->bcn_wpa_ie = (struct ieee_types_vendor_specific *)
1603 (beacon->beacon_buf + beacon->wpa_offset);
1604 if (beacon->bcn_rsn_ie)
1605 beacon->bcn_rsn_ie = (struct ieee_types_generic *)
1606 (beacon->beacon_buf + beacon->rsn_offset);
1607 if (beacon->bcn_wapi_ie)
1608 beacon->bcn_wapi_ie = (struct ieee_types_generic *)
1609 (beacon->beacon_buf + beacon->wapi_offset);
1610 if (beacon->bcn_ht_cap)
1611 beacon->bcn_ht_cap = (struct ieee80211_ht_cap *)
1612 (beacon->beacon_buf + beacon->ht_cap_offset);
1613 if (beacon->bcn_ht_info)
1614 beacon->bcn_ht_info = (struct ieee80211_ht_info *)
1615 (beacon->beacon_buf + beacon->ht_info_offset);
1616 if (beacon->bcn_bss_co_2040)
1617 beacon->bcn_bss_co_2040 = (u8 *) (beacon->beacon_buf +
1618 beacon->bss_co_2040_offset);
1619 if (beacon->bcn_ext_cap)
1620 beacon->bcn_ext_cap = (u8 *) (beacon->beacon_buf +
1621 beacon->ext_cap_offset);
1622 if (beacon->bcn_obss_scan)
1623 beacon->bcn_obss_scan = (struct ieee_types_obss_scan_param *)
1624 (beacon->beacon_buf + beacon->overlap_bss_offset);
1625}
1626
1627/*
1628 * This function stores a beacon or probe response for a BSS returned
1629 * in the scan.
1630 *
1631 * This stores a new scan response or an update for a previous scan response.
1632 * New entries need to verify that they do not exceed the total amount of
1633 * memory allocated for the table.
1634 *
1635 * Replacement entries need to take into consideration the amount of space
1636 * currently allocated for the beacon/probe response and adjust the entry
1637 * as needed.
1638 *
1639 * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
1640 * for an entry in case it is a beacon since a probe response for the
1641 * network will by larger per the standard. This helps to reduce the
1642 * amount of memory copying to fit a new probe response into an entry
1643 * already occupied by a network's previously stored beacon.
1644 */
1645static void
1646mwifiex_ret_802_11_scan_store_beacon(struct mwifiex_private *priv,
1647 u32 beacon_idx, u32 num_of_ent,
1648 struct mwifiex_bssdescriptor *new_beacon)
1649{
1650 struct mwifiex_adapter *adapter = priv->adapter;
1651 u8 *bcn_store;
1652 u32 new_bcn_size;
1653 u32 old_bcn_size;
1654 u32 bcn_space;
1655
1656 if (adapter->scan_table[beacon_idx].beacon_buf) {
1657
1658 new_bcn_size = new_beacon->beacon_buf_size;
1659 old_bcn_size = adapter->scan_table[beacon_idx].beacon_buf_size;
1660 bcn_space = adapter->scan_table[beacon_idx].beacon_buf_size_max;
1661 bcn_store = adapter->scan_table[beacon_idx].beacon_buf;
1662
1663 /* Set the max to be the same as current entry unless changed
1664 below */
1665 new_beacon->beacon_buf_size_max = bcn_space;
1666 if (new_bcn_size == old_bcn_size) {
1667 /*
1668 * Beacon is the same size as the previous entry.
1669 * Replace the previous contents with the scan result
1670 */
1671 memcpy(bcn_store, new_beacon->beacon_buf,
1672 new_beacon->beacon_buf_size);
1673
1674 } else if (new_bcn_size <= bcn_space) {
1675 /*
1676 * New beacon size will fit in the amount of space
1677 * we have previously allocated for it
1678 */
1679
1680 /* Copy the new beacon buffer entry over the old one */
1681 memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
1682
1683 /*
1684 * If the old beacon size was less than the maximum
1685 * we had alloted for the entry, and the new entry
1686 * is even smaller, reset the max size to the old
1687 * beacon entry and compress the storage space
1688 * (leaving a new pad space of (old_bcn_size -
1689 * new_bcn_size).
1690 */
1691 if (old_bcn_size < bcn_space
1692 && new_bcn_size <= old_bcn_size) {
1693 /*
1694 * Old Beacon size is smaller than the alloted
1695 * storage size. Shrink the alloted storage
1696 * space.
1697 */
1698 dev_dbg(adapter->dev, "info: AppControl:"
1699 " smaller duplicate beacon "
1700 "(%d), old = %d, new = %d, space = %d,"
1701 "left = %d\n",
1702 beacon_idx, old_bcn_size, new_bcn_size,
1703 bcn_space,
1704 (int)(sizeof(adapter->bcn_buf) -
1705 (adapter->bcn_buf_end -
1706 adapter->bcn_buf)));
1707
1708 /*
1709 * memmove (since the memory overlaps) the
1710 * data after the beacon we just stored to the
1711 * end of the current beacon. This cleans up
1712 * any unused space the old larger beacon was
1713 * using in the buffer
1714 */
1715 memmove(bcn_store + old_bcn_size,
1716 bcn_store + bcn_space,
1717 adapter->bcn_buf_end - (bcn_store +
1718 bcn_space));
1719
1720 /*
1721 * Decrement the end pointer by the difference
1722 * between the old larger size and the new
1723 * smaller size since we are using less space
1724 * due to the new beacon being smaller
1725 */
1726 adapter->bcn_buf_end -=
1727 (bcn_space - old_bcn_size);
1728
1729 /* Set the maximum storage size to the old
1730 beacon size */
1731 new_beacon->beacon_buf_size_max = old_bcn_size;
1732
1733 /* Adjust beacon buffer pointers that are past
1734 the current */
1735 mwifiex_adjust_beacon_buffer_ptrs(priv, 0,
1736 bcn_store, (bcn_space - old_bcn_size),
1737 num_of_ent);
1738 }
1739 } else if (adapter->bcn_buf_end + (new_bcn_size - bcn_space)
1740 < (adapter->bcn_buf + sizeof(adapter->bcn_buf))) {
1741 /*
1742 * Beacon is larger than space previously allocated
1743 * (bcn_space) and there is enough space left in the
1744 * beaconBuffer to store the additional data
1745 */
1746 dev_dbg(adapter->dev, "info: AppControl:"
1747 " larger duplicate beacon (%d), "
1748 "old = %d, new = %d, space = %d, left = %d\n",
1749 beacon_idx, old_bcn_size, new_bcn_size,
1750 bcn_space,
1751 (int)(sizeof(adapter->bcn_buf) -
1752 (adapter->bcn_buf_end -
1753 adapter->bcn_buf)));
1754
1755 /*
1756 * memmove (since the memory overlaps) the data
1757 * after the beacon we just stored to the end of
1758 * the current beacon. This moves the data for
1759 * the beacons after this further in memory to
1760 * make space for the new larger beacon we are
1761 * about to copy in.
1762 */
1763 memmove(bcn_store + new_bcn_size,
1764 bcn_store + bcn_space,
1765 adapter->bcn_buf_end - (bcn_store + bcn_space));
1766
1767 /* Copy the new beacon buffer entry over the old one */
1768 memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
1769
1770 /* Move the beacon end pointer by the amount of new
1771 beacon data we are adding */
1772 adapter->bcn_buf_end += (new_bcn_size - bcn_space);
1773
1774 /*
1775 * This entry is bigger than the alloted max space
1776 * previously reserved. Increase the max space to
1777 * be equal to the new beacon size
1778 */
1779 new_beacon->beacon_buf_size_max = new_bcn_size;
1780
1781 /* Adjust beacon buffer pointers that are past the
1782 current */
1783 mwifiex_adjust_beacon_buffer_ptrs(priv, 1, bcn_store,
1784 (new_bcn_size - bcn_space),
1785 num_of_ent);
1786 } else {
1787 /*
1788 * Beacon is larger than the previously allocated space,
1789 * but there is not enough free space to store the
1790 * additional data.
1791 */
1792 dev_err(adapter->dev, "AppControl: larger duplicate "
1793 " beacon (%d), old = %d new = %d, space = %d,"
1794 " left = %d\n", beacon_idx, old_bcn_size,
1795 new_bcn_size, bcn_space,
1796 (int)(sizeof(adapter->bcn_buf) -
1797 (adapter->bcn_buf_end - adapter->bcn_buf)));
1798
1799 /* Storage failure, keep old beacon intact */
1800 new_beacon->beacon_buf_size = old_bcn_size;
1801 if (new_beacon->bcn_wpa_ie)
1802 new_beacon->wpa_offset =
1803 adapter->scan_table[beacon_idx].
1804 wpa_offset;
1805 if (new_beacon->bcn_rsn_ie)
1806 new_beacon->rsn_offset =
1807 adapter->scan_table[beacon_idx].
1808 rsn_offset;
1809 if (new_beacon->bcn_wapi_ie)
1810 new_beacon->wapi_offset =
1811 adapter->scan_table[beacon_idx].
1812 wapi_offset;
1813 if (new_beacon->bcn_ht_cap)
1814 new_beacon->ht_cap_offset =
1815 adapter->scan_table[beacon_idx].
1816 ht_cap_offset;
1817 if (new_beacon->bcn_ht_info)
1818 new_beacon->ht_info_offset =
1819 adapter->scan_table[beacon_idx].
1820 ht_info_offset;
1821 if (new_beacon->bcn_bss_co_2040)
1822 new_beacon->bss_co_2040_offset =
1823 adapter->scan_table[beacon_idx].
1824 bss_co_2040_offset;
1825 if (new_beacon->bcn_ext_cap)
1826 new_beacon->ext_cap_offset =
1827 adapter->scan_table[beacon_idx].
1828 ext_cap_offset;
1829 if (new_beacon->bcn_obss_scan)
1830 new_beacon->overlap_bss_offset =
1831 adapter->scan_table[beacon_idx].
1832 overlap_bss_offset;
1833 }
1834 /* Point the new entry to its permanent storage space */
1835 new_beacon->beacon_buf = bcn_store;
1836 mwifiex_update_beacon_buffer_ptrs(new_beacon);
1837 } else {
1838 /*
1839 * No existing beacon data exists for this entry, check to see
1840 * if we can fit it in the remaining space
1841 */
1842 if (adapter->bcn_buf_end + new_beacon->beacon_buf_size +
1843 SCAN_BEACON_ENTRY_PAD < (adapter->bcn_buf +
1844 sizeof(adapter->bcn_buf))) {
1845
1846 /*
1847 * Copy the beacon buffer data from the local entry to
1848 * the adapter dev struct buffer space used to store
1849 * the raw beacon data for each entry in the scan table
1850 */
1851 memcpy(adapter->bcn_buf_end, new_beacon->beacon_buf,
1852 new_beacon->beacon_buf_size);
1853
1854 /* Update the beacon ptr to point to the table save
1855 area */
1856 new_beacon->beacon_buf = adapter->bcn_buf_end;
1857 new_beacon->beacon_buf_size_max =
1858 (new_beacon->beacon_buf_size +
1859 SCAN_BEACON_ENTRY_PAD);
1860
1861 mwifiex_update_beacon_buffer_ptrs(new_beacon);
1862
1863 /* Increment the end pointer by the size reserved */
1864 adapter->bcn_buf_end += new_beacon->beacon_buf_size_max;
1865
1866 dev_dbg(adapter->dev, "info: AppControl: beacon[%02d]"
1867 " sz=%03d, used = %04d, left = %04d\n",
1868 beacon_idx,
1869 new_beacon->beacon_buf_size,
1870 (int)(adapter->bcn_buf_end - adapter->bcn_buf),
1871 (int)(sizeof(adapter->bcn_buf) -
1872 (adapter->bcn_buf_end -
1873 adapter->bcn_buf)));
1874 } else {
1875 /* No space for new beacon */
1876 dev_dbg(adapter->dev, "info: AppControl: no space for"
1877 " beacon (%d): %pM sz=%03d, left=%03d\n",
1878 beacon_idx, new_beacon->mac_address,
1879 new_beacon->beacon_buf_size,
1880 (int)(sizeof(adapter->bcn_buf) -
1881 (adapter->bcn_buf_end -
1882 adapter->bcn_buf)));
1883
1884 /* Storage failure; clear storage records for this
1885 bcn */
1886 new_beacon->beacon_buf = NULL;
1887 new_beacon->beacon_buf_size = 0;
1888 new_beacon->beacon_buf_size_max = 0;
1889 new_beacon->bcn_wpa_ie = NULL;
1890 new_beacon->wpa_offset = 0;
1891 new_beacon->bcn_rsn_ie = NULL;
1892 new_beacon->rsn_offset = 0;
1893 new_beacon->bcn_wapi_ie = NULL;
1894 new_beacon->wapi_offset = 0;
1895 new_beacon->bcn_ht_cap = NULL;
1896 new_beacon->ht_cap_offset = 0;
1897 new_beacon->bcn_ht_info = NULL;
1898 new_beacon->ht_info_offset = 0;
1899 new_beacon->bcn_bss_co_2040 = NULL;
1900 new_beacon->bss_co_2040_offset = 0;
1901 new_beacon->bcn_ext_cap = NULL;
1902 new_beacon->ext_cap_offset = 0;
1903 new_beacon->bcn_obss_scan = NULL;
1904 new_beacon->overlap_bss_offset = 0;
1905 }
1906 }
1907}
1908
1909/*
1910 * This function restores a beacon buffer of the current BSS descriptor.
1911 */
1912static void mwifiex_restore_curr_bcn(struct mwifiex_private *priv)
1913{
1914 struct mwifiex_adapter *adapter = priv->adapter;
1915 struct mwifiex_bssdescriptor *curr_bss =
1916 &priv->curr_bss_params.bss_descriptor;
1917 unsigned long flags;
1918
1919 if (priv->curr_bcn_buf &&
1920 ((adapter->bcn_buf_end + priv->curr_bcn_size) <
1921 (adapter->bcn_buf + sizeof(adapter->bcn_buf)))) {
1922 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1923
1924 /* restore the current beacon buffer */
1925 memcpy(adapter->bcn_buf_end, priv->curr_bcn_buf,
1926 priv->curr_bcn_size);
1927 curr_bss->beacon_buf = adapter->bcn_buf_end;
1928 curr_bss->beacon_buf_size = priv->curr_bcn_size;
1929 adapter->bcn_buf_end += priv->curr_bcn_size;
1930
1931 /* adjust the pointers in the current BSS descriptor */
1932 if (curr_bss->bcn_wpa_ie)
1933 curr_bss->bcn_wpa_ie =
1934 (struct ieee_types_vendor_specific *)
1935 (curr_bss->beacon_buf +
1936 curr_bss->wpa_offset);
1937
1938 if (curr_bss->bcn_rsn_ie)
1939 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
1940 (curr_bss->beacon_buf +
1941 curr_bss->rsn_offset);
1942
1943 if (curr_bss->bcn_ht_cap)
1944 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
1945 (curr_bss->beacon_buf +
1946 curr_bss->ht_cap_offset);
1947
1948 if (curr_bss->bcn_ht_info)
1949 curr_bss->bcn_ht_info = (struct ieee80211_ht_info *)
1950 (curr_bss->beacon_buf +
1951 curr_bss->ht_info_offset);
1952
1953 if (curr_bss->bcn_bss_co_2040)
1954 curr_bss->bcn_bss_co_2040 =
1955 (u8 *) (curr_bss->beacon_buf +
1956 curr_bss->bss_co_2040_offset);
1957
1958 if (curr_bss->bcn_ext_cap)
1959 curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf +
1960 curr_bss->ext_cap_offset);
1961
1962 if (curr_bss->bcn_obss_scan)
1963 curr_bss->bcn_obss_scan =
1964 (struct ieee_types_obss_scan_param *)
1965 (curr_bss->beacon_buf +
1966 curr_bss->overlap_bss_offset);
1967
1968 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1969
1970 dev_dbg(adapter->dev, "info: current beacon restored %d\n",
1971 priv->curr_bcn_size);
1972 } else {
1973 dev_warn(adapter->dev,
1974 "curr_bcn_buf not saved or bcn_buf has no space\n");
1975 }
1976}
1977
1978/*
1979 * This function post processes the scan table after a new scan command has
1980 * completed.
1981 *
1982 * It inspects each entry of the scan table and tries to find an entry that
1983 * matches with our current associated/joined network from the scan. If
1984 * one is found, the stored copy of the BSS descriptor of our current network
1985 * is updated.
1986 *
1987 * It also debug dumps the current scan table contents after processing is over.
1988 */
1989static void
1990mwifiex_process_scan_results(struct mwifiex_private *priv)
1991{
1992 struct mwifiex_adapter *adapter = priv->adapter;
1993 s32 j;
1994 u32 i;
1995 unsigned long flags;
1996
1997 if (priv->media_connected) {
1998
1999 j = mwifiex_find_ssid_in_list(priv, &priv->curr_bss_params.
2000 bss_descriptor.ssid,
2001 priv->curr_bss_params.
2002 bss_descriptor.mac_address,
2003 priv->bss_mode);
2004
2005 if (j >= 0) {
2006 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
2007 priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
2008 priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
2009 priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
2010 priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
2011 priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
2012 priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
2013 priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
2014 priv->curr_bss_params.bss_descriptor.ht_cap_offset =
2015 0;
2016 priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL;
2017 priv->curr_bss_params.bss_descriptor.ht_info_offset =
2018 0;
2019 priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 =
2020 NULL;
2021 priv->curr_bss_params.bss_descriptor.
2022 bss_co_2040_offset = 0;
2023 priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
2024 priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
2025 priv->curr_bss_params.bss_descriptor.
2026 bcn_obss_scan = NULL;
2027 priv->curr_bss_params.bss_descriptor.
2028 overlap_bss_offset = 0;
2029 priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
2030 priv->curr_bss_params.bss_descriptor.beacon_buf_size =
2031 0;
2032 priv->curr_bss_params.bss_descriptor.
2033 beacon_buf_size_max = 0;
2034
2035 dev_dbg(adapter->dev, "info: Found current ssid/bssid"
2036 " in list @ index #%d\n", j);
2037 /* Make a copy of current BSSID descriptor */
2038 memcpy(&priv->curr_bss_params.bss_descriptor,
2039 &adapter->scan_table[j],
2040 sizeof(priv->curr_bss_params.bss_descriptor));
2041
2042 mwifiex_save_curr_bcn(priv);
2043 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
2044
2045 } else {
2046 mwifiex_restore_curr_bcn(priv);
2047 }
2048 }
2049
2050 for (i = 0; i < adapter->num_in_scan_table; i++)
2051 dev_dbg(adapter->dev, "info: scan:(%02d) %pM "
2052 "RSSI[%03d], SSID[%s]\n",
2053 i, adapter->scan_table[i].mac_address,
2054 (s32) adapter->scan_table[i].rssi,
2055 adapter->scan_table[i].ssid.ssid);
2056}
2057
2058/*
2059 * This function converts radio type scan parameter to a band configuration 1295 * This function converts radio type scan parameter to a band configuration
2060 * to be used in join command. 1296 * to be used in join command.
2061 */ 1297 */
@@ -2072,175 +1308,6 @@ mwifiex_radio_type_to_band(u8 radio_type)
2072} 1308}
2073 1309
2074/* 1310/*
2075 * This function deletes a specific indexed entry from the scan table.
2076 *
2077 * This also compacts the remaining entries and adjusts any buffering
2078 * of beacon/probe response data if needed.
2079 */
2080static void
2081mwifiex_scan_delete_table_entry(struct mwifiex_private *priv, s32 table_idx)
2082{
2083 struct mwifiex_adapter *adapter = priv->adapter;
2084 u32 del_idx;
2085 u32 beacon_buf_adj;
2086 u8 *beacon_buf;
2087
2088 /*
2089 * Shift the saved beacon buffer data for the scan table back over the
2090 * entry being removed. Update the end of buffer pointer. Save the
2091 * deleted buffer allocation size for pointer adjustments for entries
2092 * compacted after the deleted index.
2093 */
2094 beacon_buf_adj = adapter->scan_table[table_idx].beacon_buf_size_max;
2095
2096 dev_dbg(adapter->dev, "info: Scan: Delete Entry %d, beacon buffer "
2097 "removal = %d bytes\n", table_idx, beacon_buf_adj);
2098
2099 /* Check if the table entry had storage allocated for its beacon */
2100 if (beacon_buf_adj) {
2101 beacon_buf = adapter->scan_table[table_idx].beacon_buf;
2102
2103 /*
2104 * Remove the entry's buffer space, decrement the table end
2105 * pointer by the amount we are removing
2106 */
2107 adapter->bcn_buf_end -= beacon_buf_adj;
2108
2109 dev_dbg(adapter->dev, "info: scan: delete entry %d,"
2110 " compact data: %p <- %p (sz = %d)\n",
2111 table_idx, beacon_buf,
2112 beacon_buf + beacon_buf_adj,
2113 (int)(adapter->bcn_buf_end - beacon_buf));
2114
2115 /*
2116 * Compact data storage. Copy all data after the deleted
2117 * entry's end address (beacon_buf + beacon_buf_adj) back
2118 * to the original start address (beacon_buf).
2119 *
2120 * Scan table entries affected by the move will have their
2121 * entry pointer adjusted below.
2122 *
2123 * Use memmove since the dest/src memory regions overlap.
2124 */
2125 memmove(beacon_buf, beacon_buf + beacon_buf_adj,
2126 adapter->bcn_buf_end - beacon_buf);
2127 }
2128
2129 dev_dbg(adapter->dev,
2130 "info: Scan: Delete Entry %d, num_in_scan_table = %d\n",
2131 table_idx, adapter->num_in_scan_table);
2132
2133 /* Shift all of the entries after the table_idx back by one, compacting
2134 the table and removing the requested entry */
2135 for (del_idx = table_idx; (del_idx + 1) < adapter->num_in_scan_table;
2136 del_idx++) {
2137 /* Copy the next entry over this one */
2138 memcpy(adapter->scan_table + del_idx,
2139 adapter->scan_table + del_idx + 1,
2140 sizeof(struct mwifiex_bssdescriptor));
2141
2142 /*
2143 * Adjust this entry's pointer to its beacon buffer based on
2144 * the removed/compacted entry from the deleted index. Don't
2145 * decrement if the buffer pointer is NULL (no data stored for
2146 * this entry).
2147 */
2148 if (adapter->scan_table[del_idx].beacon_buf) {
2149 adapter->scan_table[del_idx].beacon_buf -=
2150 beacon_buf_adj;
2151 if (adapter->scan_table[del_idx].bcn_wpa_ie)
2152 adapter->scan_table[del_idx].bcn_wpa_ie =
2153 (struct ieee_types_vendor_specific *)
2154 (adapter->scan_table[del_idx].
2155 beacon_buf +
2156 adapter->scan_table[del_idx].
2157 wpa_offset);
2158 if (adapter->scan_table[del_idx].bcn_rsn_ie)
2159 adapter->scan_table[del_idx].bcn_rsn_ie =
2160 (struct ieee_types_generic *)
2161 (adapter->scan_table[del_idx].
2162 beacon_buf +
2163 adapter->scan_table[del_idx].
2164 rsn_offset);
2165 if (adapter->scan_table[del_idx].bcn_wapi_ie)
2166 adapter->scan_table[del_idx].bcn_wapi_ie =
2167 (struct ieee_types_generic *)
2168 (adapter->scan_table[del_idx].beacon_buf
2169 + adapter->scan_table[del_idx].
2170 wapi_offset);
2171 if (adapter->scan_table[del_idx].bcn_ht_cap)
2172 adapter->scan_table[del_idx].bcn_ht_cap =
2173 (struct ieee80211_ht_cap *)
2174 (adapter->scan_table[del_idx].beacon_buf
2175 + adapter->scan_table[del_idx].
2176 ht_cap_offset);
2177
2178 if (adapter->scan_table[del_idx].bcn_ht_info)
2179 adapter->scan_table[del_idx].bcn_ht_info =
2180 (struct ieee80211_ht_info *)
2181 (adapter->scan_table[del_idx].beacon_buf
2182 + adapter->scan_table[del_idx].
2183 ht_info_offset);
2184 if (adapter->scan_table[del_idx].bcn_bss_co_2040)
2185 adapter->scan_table[del_idx].bcn_bss_co_2040 =
2186 (u8 *)
2187 (adapter->scan_table[del_idx].beacon_buf
2188 + adapter->scan_table[del_idx].
2189 bss_co_2040_offset);
2190 if (adapter->scan_table[del_idx].bcn_ext_cap)
2191 adapter->scan_table[del_idx].bcn_ext_cap =
2192 (u8 *)
2193 (adapter->scan_table[del_idx].beacon_buf
2194 + adapter->scan_table[del_idx].
2195 ext_cap_offset);
2196 if (adapter->scan_table[del_idx].bcn_obss_scan)
2197 adapter->scan_table[del_idx].
2198 bcn_obss_scan =
2199 (struct ieee_types_obss_scan_param *)
2200 (adapter->scan_table[del_idx].beacon_buf
2201 + adapter->scan_table[del_idx].
2202 overlap_bss_offset);
2203 }
2204 }
2205
2206 /* The last entry is invalid now that it has been deleted or moved
2207 back */
2208 memset(adapter->scan_table + adapter->num_in_scan_table - 1,
2209 0x00, sizeof(struct mwifiex_bssdescriptor));
2210
2211 adapter->num_in_scan_table--;
2212}
2213
2214/*
2215 * This function deletes all occurrences of a given SSID from the scan table.
2216 *
2217 * This iterates through the scan table and deletes all entries that match
2218 * the given SSID. It also compacts the remaining scan table entries.
2219 */
2220static int
2221mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
2222 struct mwifiex_802_11_ssid *del_ssid)
2223{
2224 s32 table_idx = -1;
2225
2226 dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n",
2227 del_ssid->ssid);
2228
2229 /* If the requested SSID is found in the table, delete it. Then keep
2230 searching the table for multiple entires for the SSID until no
2231 more are found */
2232 while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL,
2233 NL80211_IFTYPE_UNSPECIFIED)) >= 0) {
2234 dev_dbg(priv->adapter->dev,
2235 "info: Scan: Delete SSID Entry: Found Idx = %d\n",
2236 table_idx);
2237 mwifiex_scan_delete_table_entry(priv, table_idx);
2238 }
2239
2240 return table_idx == -1 ? -1 : 0;
2241}
2242
2243/*
2244 * This is an internal function used to start a scan based on an input 1311 * This is an internal function used to start a scan based on an input
2245 * configuration. 1312 * configuration.
2246 * 1313 *
@@ -2258,7 +1325,6 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
2258 struct mwifiex_ie_types_chan_list_param_set *chan_list_out; 1325 struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
2259 u32 buf_size; 1326 u32 buf_size;
2260 struct mwifiex_chan_scan_param_set *scan_chan_list; 1327 struct mwifiex_chan_scan_param_set *scan_chan_list;
2261 u8 keep_previous_scan;
2262 u8 filtered_scan; 1328 u8 filtered_scan;
2263 u8 scan_current_chan_only; 1329 u8 scan_current_chan_only;
2264 u8 max_chan_per_scan; 1330 u8 max_chan_per_scan;
@@ -2295,24 +1361,11 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
2295 return -ENOMEM; 1361 return -ENOMEM;
2296 } 1362 }
2297 1363
2298 keep_previous_scan = false;
2299
2300 mwifiex_scan_setup_scan_config(priv, user_scan_in, 1364 mwifiex_scan_setup_scan_config(priv, user_scan_in,
2301 &scan_cfg_out->config, &chan_list_out, 1365 &scan_cfg_out->config, &chan_list_out,
2302 scan_chan_list, &max_chan_per_scan, 1366 scan_chan_list, &max_chan_per_scan,
2303 &filtered_scan, &scan_current_chan_only); 1367 &filtered_scan, &scan_current_chan_only);
2304 1368
2305 if (user_scan_in)
2306 keep_previous_scan = user_scan_in->keep_previous_scan;
2307
2308
2309 if (!keep_previous_scan) {
2310 memset(adapter->scan_table, 0x00,
2311 sizeof(struct mwifiex_bssdescriptor) * MWIFIEX_MAX_AP);
2312 adapter->num_in_scan_table = 0;
2313 adapter->bcn_buf_end = adapter->bcn_buf;
2314 }
2315
2316 ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan, 1369 ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
2317 &scan_cfg_out->config, chan_list_out, 1370 &scan_cfg_out->config, chan_list_out,
2318 scan_chan_list); 1371 scan_chan_list);
@@ -2379,6 +1432,107 @@ int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
2379} 1432}
2380 1433
2381/* 1434/*
1435 * This function checks compatibility of requested network with current
1436 * driver settings.
1437 */
1438int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1439 struct mwifiex_bssdescriptor *bss_desc)
1440{
1441 int ret = -1;
1442
1443 if (!bss_desc)
1444 return -1;
1445
1446 if ((mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
1447 (u8) bss_desc->bss_band, (u16) bss_desc->channel))) {
1448 switch (priv->bss_mode) {
1449 case NL80211_IFTYPE_STATION:
1450 case NL80211_IFTYPE_ADHOC:
1451 ret = mwifiex_is_network_compatible(priv, bss_desc,
1452 priv->bss_mode);
1453 if (ret)
1454 dev_err(priv->adapter->dev, "cannot find ssid "
1455 "%s\n", bss_desc->ssid.ssid);
1456 break;
1457 default:
1458 ret = 0;
1459 }
1460 }
1461
1462 return ret;
1463}
1464
1465static int
1466mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1467 u8 *bssid, s32 rssi, const u8 *ie_buf,
1468 size_t ie_len, u16 beacon_period, u16 cap_info_bitmap)
1469{
1470 struct mwifiex_bssdescriptor *bss_desc = NULL;
1471 int ret;
1472 unsigned long flags;
1473 u8 *beacon_ie;
1474
1475 /* Allocate and fill new bss descriptor */
1476 bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
1477 GFP_KERNEL);
1478 if (!bss_desc) {
1479 dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
1480 return -ENOMEM;
1481 }
1482 beacon_ie = kzalloc(ie_len, GFP_KERNEL);
1483 if (!bss_desc) {
1484 dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
1485 return -ENOMEM;
1486 }
1487 memcpy(beacon_ie, ie_buf, ie_len);
1488
1489 ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie,
1490 ie_len, beacon_period,
1491 cap_info_bitmap, bss_desc);
1492 if (ret)
1493 goto done;
1494
1495 ret = mwifiex_check_network_compatibility(priv, bss_desc);
1496 if (ret)
1497 goto done;
1498
1499 /* Update current bss descriptor parameters */
1500 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1501 priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
1502 priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
1503 priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
1504 priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
1505 priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
1506 priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
1507 priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
1508 priv->curr_bss_params.bss_descriptor.ht_cap_offset =
1509 0;
1510 priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL;
1511 priv->curr_bss_params.bss_descriptor.ht_info_offset =
1512 0;
1513 priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 =
1514 NULL;
1515 priv->curr_bss_params.bss_descriptor.
1516 bss_co_2040_offset = 0;
1517 priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
1518 priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
1519 priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
1520 priv->curr_bss_params.bss_descriptor.beacon_buf_size =
1521 0;
1522
1523 /* Make a copy of current BSSID descriptor */
1524 memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1525 sizeof(priv->curr_bss_params.bss_descriptor));
1526 mwifiex_save_curr_bcn(priv);
1527 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1528
1529done:
1530 kfree(bss_desc);
1531 kfree(beacon_ie);
1532 return 0;
1533}
1534
1535/*
2382 * This function handles the command response of scan. 1536 * This function handles the command response of scan.
2383 * 1537 *
2384 * The response buffer for the scan command has the following 1538 * The response buffer for the scan command has the following
@@ -2404,21 +1558,16 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2404 struct mwifiex_adapter *adapter = priv->adapter; 1558 struct mwifiex_adapter *adapter = priv->adapter;
2405 struct cmd_ctrl_node *cmd_node; 1559 struct cmd_ctrl_node *cmd_node;
2406 struct host_cmd_ds_802_11_scan_rsp *scan_rsp; 1560 struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
2407 struct mwifiex_bssdescriptor *bss_new_entry = NULL;
2408 struct mwifiex_ie_types_data *tlv_data; 1561 struct mwifiex_ie_types_data *tlv_data;
2409 struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; 1562 struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2410 u8 *bss_info; 1563 u8 *bss_info;
2411 u32 scan_resp_size; 1564 u32 scan_resp_size;
2412 u32 bytes_left; 1565 u32 bytes_left;
2413 u32 num_in_table;
2414 u32 bss_idx;
2415 u32 idx; 1566 u32 idx;
2416 u32 tlv_buf_size; 1567 u32 tlv_buf_size;
2417 long long tsf_val;
2418 struct mwifiex_chan_freq_power *cfp; 1568 struct mwifiex_chan_freq_power *cfp;
2419 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; 1569 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2420 struct chan_band_param_set *chan_band; 1570 struct chan_band_param_set *chan_band;
2421 u8 band;
2422 u8 is_bgscan_resp; 1571 u8 is_bgscan_resp;
2423 unsigned long flags; 1572 unsigned long flags;
2424 1573
@@ -2447,7 +1596,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2447 "info: SCAN_RESP: returned %d APs before parsing\n", 1596 "info: SCAN_RESP: returned %d APs before parsing\n",
2448 scan_rsp->number_of_sets); 1597 scan_rsp->number_of_sets);
2449 1598
2450 num_in_table = adapter->num_in_scan_table;
2451 bss_info = scan_rsp->bss_desc_and_tlv_buffer; 1599 bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2452 1600
2453 /* 1601 /*
@@ -2479,125 +1627,147 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2479 (struct mwifiex_ie_types_data **) 1627 (struct mwifiex_ie_types_data **)
2480 &chan_band_tlv); 1628 &chan_band_tlv);
2481 1629
2482 /*
2483 * Process each scan response returned (scan_rsp->number_of_sets).
2484 * Save the information in the bss_new_entry and then insert into the
2485 * driver scan table either as an update to an existing entry
2486 * or as an addition at the end of the table
2487 */
2488 bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor),
2489 GFP_KERNEL);
2490 if (!bss_new_entry) {
2491 dev_err(adapter->dev, " failed to alloc bss_new_entry\n");
2492 return -ENOMEM;
2493 }
2494
2495 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { 1630 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2496 /* Zero out the bss_new_entry we are about to store info in */ 1631 u8 bssid[ETH_ALEN];
2497 memset(bss_new_entry, 0x00, 1632 s32 rssi;
2498 sizeof(struct mwifiex_bssdescriptor)); 1633 const u8 *ie_buf;
2499 1634 size_t ie_len;
2500 if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry, 1635 int channel = -1;
2501 &bss_info, 1636 u64 network_tsf = 0;
2502 &bytes_left)) { 1637 u16 beacon_size = 0;
2503 /* Error parsing/interpreting scan response, skipped */ 1638 u32 curr_bcn_bytes;
2504 dev_err(adapter->dev, "SCAN_RESP: " 1639 u32 freq;
2505 "mwifiex_interpret_bss_desc_with_ie " 1640 u16 beacon_period;
2506 "returned ERROR\n"); 1641 u16 cap_info_bitmap;
2507 continue; 1642 u8 *current_ptr;
1643 struct mwifiex_bcn_param *bcn_param;
1644
1645 if (bytes_left >= sizeof(beacon_size)) {
1646 /* Extract & convert beacon size from command buffer */
1647 memcpy(&beacon_size, bss_info, sizeof(beacon_size));
1648 bytes_left -= sizeof(beacon_size);
1649 bss_info += sizeof(beacon_size);
2508 } 1650 }
2509 1651
2510 /* Process the data fields and IEs returned for this BSS */ 1652 if (!beacon_size || beacon_size > bytes_left) {
2511 dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n", 1653 bss_info += bytes_left;
2512 bss_new_entry->mac_address); 1654 bytes_left = 0;
1655 return -1;
1656 }
2513 1657
2514 /* Search the scan table for the same bssid */ 1658 /* Initialize the current working beacon pointer for this BSS
2515 for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) { 1659 * iteration */
2516 if (memcmp(bss_new_entry->mac_address, 1660 current_ptr = bss_info;
2517 adapter->scan_table[bss_idx].mac_address, 1661
2518 sizeof(bss_new_entry->mac_address))) { 1662 /* Advance the return beacon pointer past the current beacon */
2519 continue; 1663 bss_info += beacon_size;
1664 bytes_left -= beacon_size;
1665
1666 curr_bcn_bytes = beacon_size;
1667
1668 /*
1669 * First 5 fields are bssid, RSSI, time stamp, beacon interval,
1670 * and capability information
1671 */
1672 if (curr_bcn_bytes < sizeof(struct mwifiex_bcn_param)) {
1673 dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
1674 continue;
1675 }
1676 bcn_param = (struct mwifiex_bcn_param *)current_ptr;
1677 current_ptr += sizeof(*bcn_param);
1678 curr_bcn_bytes -= sizeof(*bcn_param);
1679
1680 memcpy(bssid, bcn_param->bssid, ETH_ALEN);
1681
1682 rssi = (s32) (bcn_param->rssi);
1683 dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n",
1684 rssi);
1685
1686 beacon_period = le16_to_cpu(bcn_param->beacon_period);
1687
1688 cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1689 dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
1690 cap_info_bitmap);
1691
1692 /* Rest of the current buffer are IE's */
1693 ie_buf = current_ptr;
1694 ie_len = curr_bcn_bytes;
1695 dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP"
1696 " = %d\n", curr_bcn_bytes);
1697
1698 while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1699 u8 element_id, element_len;
1700
1701 element_id = *current_ptr;
1702 element_len = *(current_ptr + 1);
1703 if (curr_bcn_bytes < element_len +
1704 sizeof(struct ieee_types_header)) {
1705 dev_err(priv->adapter->dev, "%s: in processing"
1706 " IE, bytes left < IE length\n",
1707 __func__);
1708 goto done;
2520 } 1709 }
2521 /* 1710 if (element_id == WLAN_EID_DS_PARAMS) {
2522 * If the SSID matches as well, it is a 1711 channel = *(u8 *) (current_ptr +
2523 * duplicate of this entry. Keep the bss_idx 1712 sizeof(struct ieee_types_header));
2524 * set to this entry so we replace the old
2525 * contents in the table
2526 */
2527 if ((bss_new_entry->ssid.ssid_len
2528 == adapter->scan_table[bss_idx]. ssid.ssid_len)
2529 && (!memcmp(bss_new_entry->ssid.ssid,
2530 adapter->scan_table[bss_idx].ssid.ssid,
2531 bss_new_entry->ssid.ssid_len))) {
2532 dev_dbg(adapter->dev, "info: SCAN_RESP:"
2533 " duplicate of index: %d\n", bss_idx);
2534 break; 1713 break;
2535 } 1714 }
2536 } 1715
2537 /* 1716 current_ptr += element_len +
2538 * If the bss_idx is equal to the number of entries in 1717 sizeof(struct ieee_types_header);
2539 * the table, the new entry was not a duplicate; append 1718 curr_bcn_bytes -= element_len +
2540 * it to the scan table 1719 sizeof(struct ieee_types_header);
2541 */
2542 if (bss_idx == num_in_table) {
2543 /* Range check the bss_idx, keep it limited to
2544 the last entry */
2545 if (bss_idx == MWIFIEX_MAX_AP)
2546 bss_idx--;
2547 else
2548 num_in_table++;
2549 } 1720 }
2550 1721
2551 /* 1722 /*
2552 * Save the beacon/probe response returned for later application
2553 * retrieval. Duplicate beacon/probe responses are updated if
2554 * possible
2555 */
2556 mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx,
2557 num_in_table, bss_new_entry);
2558 /*
2559 * If the TSF TLV was appended to the scan results, save this 1723 * If the TSF TLV was appended to the scan results, save this
2560 * entry's TSF value in the networkTSF field.The networkTSF is 1724 * entry's TSF value in the networkTSF field.The networkTSF is
2561 * the firmware's TSF value at the time the beacon or probe 1725 * the firmware's TSF value at the time the beacon or probe
2562 * response was received. 1726 * response was received.
2563 */ 1727 */
2564 if (tsf_tlv) { 1728 if (tsf_tlv)
2565 memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE] 1729 memcpy(&network_tsf,
2566 , sizeof(tsf_val)); 1730 &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
2567 memcpy(&bss_new_entry->network_tsf, &tsf_val, 1731 sizeof(network_tsf));
2568 sizeof(bss_new_entry->network_tsf)); 1732
2569 } 1733 if (channel != -1) {
2570 band = BAND_G; 1734 struct ieee80211_channel *chan;
2571 if (chan_band_tlv) { 1735 u8 band;
2572 chan_band = &chan_band_tlv->chan_band_param[idx]; 1736
2573 band = mwifiex_radio_type_to_band(chan_band->radio_type 1737 band = BAND_G;
2574 & (BIT(0) | BIT(1))); 1738 if (chan_band_tlv) {
2575 } 1739 chan_band =
2576 1740 &chan_band_tlv->chan_band_param[idx];
2577 /* Save the band designation for this entry for use in join */ 1741 band = mwifiex_radio_type_to_band(
2578 bss_new_entry->bss_band = band; 1742 chan_band->radio_type
2579 cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, 1743 & (BIT(0) | BIT(1)));
2580 (u8) bss_new_entry->bss_band, 1744 }
2581 (u16)bss_new_entry->channel);
2582 1745
2583 if (cfp) 1746 cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(
2584 bss_new_entry->freq = cfp->freq; 1747 priv, (u8)band, (u16)channel);
2585 else
2586 bss_new_entry->freq = 0;
2587 1748
2588 /* Copy the locally created bss_new_entry to the scan table */ 1749 freq = cfp ? cfp->freq : 0;
2589 memcpy(&adapter->scan_table[bss_idx], bss_new_entry,
2590 sizeof(adapter->scan_table[bss_idx]));
2591 1750
2592 } 1751 chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
2593 1752
2594 dev_dbg(adapter->dev, 1753 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
2595 "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n", 1754 cfg80211_inform_bss(priv->wdev->wiphy, chan,
2596 scan_rsp->number_of_sets, 1755 bssid, network_tsf, cap_info_bitmap,
2597 num_in_table - adapter->num_in_scan_table, num_in_table); 1756 beacon_period, ie_buf, ie_len, rssi,
1757 GFP_KERNEL);
2598 1758
2599 /* Update the total number of BSSIDs in the scan table */ 1759 if (priv->media_connected && !memcmp(bssid,
2600 adapter->num_in_scan_table = num_in_table; 1760 priv->curr_bss_params.bss_descriptor
1761 .mac_address, ETH_ALEN))
1762 mwifiex_update_curr_bss_params(priv,
1763 bssid, rssi, ie_buf,
1764 ie_len, beacon_period,
1765 cap_info_bitmap);
1766 }
1767 } else {
1768 dev_dbg(adapter->dev, "missing BSS channel IE\n");
1769 }
1770 }
2601 1771
2602 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 1772 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2603 if (list_empty(&adapter->scan_pending_q)) { 1773 if (list_empty(&adapter->scan_pending_q)) {
@@ -2605,12 +1775,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2605 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); 1775 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2606 adapter->scan_processing = false; 1776 adapter->scan_processing = false;
2607 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); 1777 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2608 /*
2609 * Process the resulting scan table:
2610 * - Remove any bad ssids
2611 * - Update our current BSS information from scan data
2612 */
2613 mwifiex_process_scan_results(priv);
2614 1778
2615 /* Need to indicate IOCTL complete */ 1779 /* Need to indicate IOCTL complete */
2616 if (adapter->curr_cmd->wait_q_enabled) { 1780 if (adapter->curr_cmd->wait_q_enabled) {
@@ -2636,7 +1800,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2636 } 1800 }
2637 1801
2638done: 1802done:
2639 kfree((u8 *) bss_new_entry);
2640 return ret; 1803 return ret;
2641} 1804}
2642 1805
@@ -2663,141 +1826,6 @@ int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2663} 1826}
2664 1827
2665/* 1828/*
2666 * This function finds a SSID in the scan table.
2667 *
2668 * A BSSID may optionally be provided to qualify the SSID.
2669 * For non-Auto mode, further check is made to make sure the
2670 * BSS found in the scan table is compatible with the current
2671 * settings of the driver.
2672 */
2673s32
2674mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
2675 struct mwifiex_802_11_ssid *ssid, u8 *bssid,
2676 u32 mode)
2677{
2678 struct mwifiex_adapter *adapter = priv->adapter;
2679 s32 net = -1, j;
2680 u8 best_rssi = 0;
2681 u32 i;
2682
2683 dev_dbg(adapter->dev, "info: num of entries in table = %d\n",
2684 adapter->num_in_scan_table);
2685
2686 /*
2687 * Loop through the table until the maximum is reached or until a match
2688 * is found based on the bssid field comparison
2689 */
2690 for (i = 0;
2691 i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0));
2692 i++) {
2693 if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) &&
2694 (!bssid
2695 || !memcmp(adapter->scan_table[i].mac_address, bssid,
2696 ETH_ALEN))
2697 &&
2698 (mwifiex_get_cfp_by_band_and_channel_from_cfg80211
2699 (priv, (u8) adapter->scan_table[i].bss_band,
2700 (u16) adapter->scan_table[i].channel))) {
2701 switch (mode) {
2702 case NL80211_IFTYPE_STATION:
2703 case NL80211_IFTYPE_ADHOC:
2704 j = mwifiex_is_network_compatible(priv, i,
2705 mode);
2706
2707 if (j >= 0) {
2708 if (SCAN_RSSI
2709 (adapter->scan_table[i].rssi) >
2710 best_rssi) {
2711 best_rssi = SCAN_RSSI(adapter->
2712 scan_table
2713 [i].rssi);
2714 net = i;
2715 }
2716 } else {
2717 if (net == -1)
2718 net = j;
2719 }
2720 break;
2721 case NL80211_IFTYPE_UNSPECIFIED:
2722 default:
2723 /*
2724 * Do not check compatibility if the mode
2725 * requested is Auto/Unknown. Allows generic
2726 * find to work without verifying against the
2727 * Adapter security settings
2728 */
2729 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
2730 best_rssi) {
2731 best_rssi = SCAN_RSSI(adapter->
2732 scan_table[i].rssi);
2733 net = i;
2734 }
2735 break;
2736 }
2737 }
2738 }
2739
2740 return net;
2741}
2742
2743/*
2744 * This function finds a specific compatible BSSID in the scan list.
2745 *
2746 * This function loops through the scan table looking for a compatible
2747 * match. If a BSSID matches, but the BSS is found to be not compatible
2748 * the function ignores it and continues to search through the rest of
2749 * the entries in case there is an AP with multiple SSIDs assigned to
2750 * the same BSSID.
2751 */
2752s32
2753mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
2754 u32 mode)
2755{
2756 struct mwifiex_adapter *adapter = priv->adapter;
2757 s32 net = -1;
2758 u32 i;
2759
2760 if (!bssid)
2761 return -1;
2762
2763 dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n",
2764 adapter->num_in_scan_table);
2765
2766 /*
2767 * Look through the scan table for a compatible match. The ret return
2768 * variable will be equal to the index in the scan table (greater
2769 * than zero) if the network is compatible. The loop will continue
2770 * past a matched bssid that is not compatible in case there is an
2771 * AP with multiple SSIDs assigned to the same BSSID
2772 */
2773 for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) {
2774 if (!memcmp
2775 (adapter->scan_table[i].mac_address, bssid, ETH_ALEN)
2776 && mwifiex_get_cfp_by_band_and_channel_from_cfg80211
2777 (priv,
2778 (u8) adapter->
2779 scan_table[i].
2780 bss_band,
2781 (u16) adapter->
2782 scan_table[i].
2783 channel)) {
2784 switch (mode) {
2785 case NL80211_IFTYPE_STATION:
2786 case NL80211_IFTYPE_ADHOC:
2787 net = mwifiex_is_network_compatible(priv, i,
2788 mode);
2789 break;
2790 default:
2791 net = i;
2792 break;
2793 }
2794 }
2795 }
2796
2797 return net;
2798}
2799
2800/*
2801 * This function inserts scan command node to the scan pending queue. 1829 * This function inserts scan command node to the scan pending queue.
2802 */ 1830 */
2803void 1831void
@@ -2814,42 +1842,6 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2814} 1842}
2815 1843
2816/* 1844/*
2817 * This function finds an AP with specific ssid in the scan list.
2818 */
2819int mwifiex_find_best_network(struct mwifiex_private *priv,
2820 struct mwifiex_ssid_bssid *req_ssid_bssid)
2821{
2822 struct mwifiex_adapter *adapter = priv->adapter;
2823 struct mwifiex_bssdescriptor *req_bss;
2824 s32 i;
2825
2826 memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
2827
2828 i = mwifiex_find_best_network_in_list(priv);
2829
2830 if (i >= 0) {
2831 req_bss = &adapter->scan_table[i];
2832 memcpy(&req_ssid_bssid->ssid, &req_bss->ssid,
2833 sizeof(struct mwifiex_802_11_ssid));
2834 memcpy((u8 *) &req_ssid_bssid->bssid,
2835 (u8 *) &req_bss->mac_address, ETH_ALEN);
2836
2837 /* Make sure we are in the right mode */
2838 if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED)
2839 priv->bss_mode = req_bss->bss_mode;
2840 }
2841
2842 if (!req_ssid_bssid->ssid.ssid_len)
2843 return -1;
2844
2845 dev_dbg(adapter->dev, "info: Best network found = [%s], "
2846 "[%pM]\n", req_ssid_bssid->ssid.ssid,
2847 req_ssid_bssid->bssid);
2848
2849 return 0;
2850}
2851
2852/*
2853 * This function sends a scan command for all available channels to the 1845 * This function sends a scan command for all available channels to the
2854 * firmware, filtered on a specific SSID. 1846 * firmware, filtered on a specific SSID.
2855 */ 1847 */
@@ -2874,8 +1866,6 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2874 return ret; 1866 return ret;
2875 } 1867 }
2876 1868
2877 mwifiex_scan_delete_ssid_table_entry(priv, req_ssid);
2878
2879 scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); 1869 scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2880 if (!scan_cfg) { 1870 if (!scan_cfg) {
2881 dev_err(adapter->dev, "failed to alloc scan_cfg\n"); 1871 dev_err(adapter->dev, "failed to alloc scan_cfg\n");
@@ -2884,7 +1874,6 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2884 1874
2885 memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, 1875 memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid,
2886 req_ssid->ssid_len); 1876 req_ssid->ssid_len);
2887 scan_cfg->keep_previous_scan = true;
2888 1877
2889 ret = mwifiex_scan_networks(priv, scan_cfg); 1878 ret = mwifiex_scan_networks(priv, scan_cfg);
2890 1879
@@ -3010,6 +1999,39 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
3010 curr_bss->beacon_buf_size); 1999 curr_bss->beacon_buf_size);
3011 dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n", 2000 dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n",
3012 priv->curr_bcn_size); 2001 priv->curr_bcn_size);
2002
2003 curr_bss->beacon_buf = priv->curr_bcn_buf;
2004
2005 /* adjust the pointers in the current BSS descriptor */
2006 if (curr_bss->bcn_wpa_ie)
2007 curr_bss->bcn_wpa_ie =
2008 (struct ieee_types_vendor_specific *)
2009 (curr_bss->beacon_buf +
2010 curr_bss->wpa_offset);
2011
2012 if (curr_bss->bcn_rsn_ie)
2013 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2014 (curr_bss->beacon_buf +
2015 curr_bss->rsn_offset);
2016
2017 if (curr_bss->bcn_ht_cap)
2018 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2019 (curr_bss->beacon_buf +
2020 curr_bss->ht_cap_offset);
2021
2022 if (curr_bss->bcn_ht_info)
2023 curr_bss->bcn_ht_info = (struct ieee80211_ht_info *)
2024 (curr_bss->beacon_buf +
2025 curr_bss->ht_info_offset);
2026
2027 if (curr_bss->bcn_bss_co_2040)
2028 curr_bss->bcn_bss_co_2040 =
2029 (u8 *) (curr_bss->beacon_buf +
2030 curr_bss->bss_co_2040_offset);
2031
2032 if (curr_bss->bcn_ext_cap)
2033 curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf +
2034 curr_bss->ext_cap_offset);
3013} 2035}
3014 2036
3015/* 2037/*