diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/scan.c')
| -rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/scan.c | 120 |
1 files changed, 92 insertions, 28 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 348b9c4b694a..7e9aa3cb3254 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
| @@ -173,15 +173,21 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_ssid_ie *cmd_ssid, | |||
| 173 | * already included in the probe template, so we need to set only | 173 | * already included in the probe template, so we need to set only |
| 174 | * req->n_ssids - 1 bits in addition to the first bit. | 174 | * req->n_ssids - 1 bits in addition to the first bit. |
| 175 | */ | 175 | */ |
| 176 | static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) | 176 | static u16 iwl_mvm_get_active_dwell(struct iwl_mvm *mvm, |
| 177 | enum ieee80211_band band, int n_ssids) | ||
| 177 | { | 178 | { |
| 179 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BASIC_DWELL) | ||
| 180 | return 10; | ||
| 178 | if (band == IEEE80211_BAND_2GHZ) | 181 | if (band == IEEE80211_BAND_2GHZ) |
| 179 | return 20 + 3 * (n_ssids + 1); | 182 | return 20 + 3 * (n_ssids + 1); |
| 180 | return 10 + 2 * (n_ssids + 1); | 183 | return 10 + 2 * (n_ssids + 1); |
| 181 | } | 184 | } |
| 182 | 185 | ||
| 183 | static u16 iwl_mvm_get_passive_dwell(enum ieee80211_band band) | 186 | static u16 iwl_mvm_get_passive_dwell(struct iwl_mvm *mvm, |
| 187 | enum ieee80211_band band) | ||
| 184 | { | 188 | { |
| 189 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BASIC_DWELL) | ||
| 190 | return 110; | ||
| 185 | return band == IEEE80211_BAND_2GHZ ? 100 + 20 : 100 + 10; | 191 | return band == IEEE80211_BAND_2GHZ ? 100 + 20 : 100 + 10; |
| 186 | } | 192 | } |
| 187 | 193 | ||
| @@ -309,18 +315,18 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, | |||
| 309 | goto not_bound; | 315 | goto not_bound; |
| 310 | 316 | ||
| 311 | params->suspend_time = 30; | 317 | params->suspend_time = 30; |
| 312 | params->max_out_time = 170; | 318 | params->max_out_time = 120; |
| 313 | 319 | ||
| 314 | if (iwl_mvm_low_latency(mvm)) { | 320 | if (iwl_mvm_low_latency(mvm)) { |
| 315 | if (mvm->fw->ucode_capa.api[0] & | 321 | if (mvm->fw->ucode_capa.api[0] & |
| 316 | IWL_UCODE_TLV_API_FRAGMENTED_SCAN) { | 322 | IWL_UCODE_TLV_API_FRAGMENTED_SCAN) { |
| 317 | params->suspend_time = 105; | 323 | params->suspend_time = 105; |
| 318 | params->max_out_time = 70; | ||
| 319 | /* | 324 | /* |
| 320 | * If there is more than one active interface make | 325 | * If there is more than one active interface make |
| 321 | * passive scan more fragmented. | 326 | * passive scan more fragmented. |
| 322 | */ | 327 | */ |
| 323 | frag_passive_dwell = (global_cnt < 2) ? 40 : 20; | 328 | frag_passive_dwell = (global_cnt < 2) ? 40 : 20; |
| 329 | params->max_out_time = frag_passive_dwell; | ||
| 324 | } else { | 330 | } else { |
| 325 | params->suspend_time = 120; | 331 | params->suspend_time = 120; |
| 326 | params->max_out_time = 120; | 332 | params->max_out_time = 120; |
| @@ -337,7 +343,8 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, | |||
| 337 | */ | 343 | */ |
| 338 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { | 344 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { |
| 339 | u32 passive_dwell = | 345 | u32 passive_dwell = |
| 340 | iwl_mvm_get_passive_dwell(IEEE80211_BAND_2GHZ); | 346 | iwl_mvm_get_passive_dwell(mvm, |
| 347 | IEEE80211_BAND_2GHZ); | ||
| 341 | params->max_out_time = passive_dwell; | 348 | params->max_out_time = passive_dwell; |
| 342 | } else { | 349 | } else { |
| 343 | params->passive_fragmented = true; | 350 | params->passive_fragmented = true; |
| @@ -354,8 +361,8 @@ not_bound: | |||
| 354 | params->dwell[band].passive = frag_passive_dwell; | 361 | params->dwell[band].passive = frag_passive_dwell; |
| 355 | else | 362 | else |
| 356 | params->dwell[band].passive = | 363 | params->dwell[band].passive = |
| 357 | iwl_mvm_get_passive_dwell(band); | 364 | iwl_mvm_get_passive_dwell(mvm, band); |
| 358 | params->dwell[band].active = iwl_mvm_get_active_dwell(band, | 365 | params->dwell[band].active = iwl_mvm_get_active_dwell(mvm, band, |
| 359 | n_ssids); | 366 | n_ssids); |
| 360 | } | 367 | } |
| 361 | } | 368 | } |
| @@ -536,6 +543,19 @@ int iwl_mvm_rx_scan_response(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 536 | return 0; | 543 | return 0; |
| 537 | } | 544 | } |
| 538 | 545 | ||
| 546 | int iwl_mvm_rx_scan_offload_iter_complete_notif(struct iwl_mvm *mvm, | ||
| 547 | struct iwl_rx_cmd_buffer *rxb, | ||
| 548 | struct iwl_device_cmd *cmd) | ||
| 549 | { | ||
| 550 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
| 551 | struct iwl_scan_complete_notif *notif = (void *)pkt->data; | ||
| 552 | |||
| 553 | IWL_DEBUG_SCAN(mvm, | ||
| 554 | "Scan offload iteration complete: status=0x%x scanned channels=%d\n", | ||
| 555 | notif->status, notif->scanned_channels); | ||
| 556 | return 0; | ||
| 557 | } | ||
| 558 | |||
| 539 | int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | 559 | int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, |
| 540 | struct iwl_device_cmd *cmd) | 560 | struct iwl_device_cmd *cmd) |
| 541 | { | 561 | { |
| @@ -684,7 +704,8 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | |||
| 684 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 704 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
| 685 | } | 705 | } |
| 686 | 706 | ||
| 687 | mvm->last_ebs_successful = !ebs_status; | 707 | if (ebs_status) |
| 708 | mvm->last_ebs_successful = false; | ||
| 688 | 709 | ||
| 689 | return 0; | 710 | return 0; |
| 690 | } | 711 | } |
| @@ -1104,6 +1125,12 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify) | |||
| 1104 | return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN, | 1125 | return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN, |
| 1105 | notify); | 1126 | notify); |
| 1106 | 1127 | ||
| 1128 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) | ||
| 1129 | return 0; | ||
| 1130 | |||
| 1131 | if (iwl_mvm_is_radio_killed(mvm)) | ||
| 1132 | goto out; | ||
| 1133 | |||
| 1107 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED && | 1134 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED && |
| 1108 | (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) || | 1135 | (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) || |
| 1109 | mvm->scan_status != IWL_MVM_SCAN_OS)) { | 1136 | mvm->scan_status != IWL_MVM_SCAN_OS)) { |
| @@ -1140,6 +1167,7 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify) | |||
| 1140 | if (mvm->scan_status == IWL_MVM_SCAN_OS) | 1167 | if (mvm->scan_status == IWL_MVM_SCAN_OS) |
| 1141 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 1168 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
| 1142 | 1169 | ||
| 1170 | out: | ||
| 1143 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 1171 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
| 1144 | 1172 | ||
| 1145 | if (notify) { | 1173 | if (notify) { |
| @@ -1296,22 +1324,6 @@ iwl_mvm_build_generic_unified_scan_cmd(struct iwl_mvm *mvm, | |||
| 1296 | cmd->scan_prio = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH); | 1324 | cmd->scan_prio = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH); |
| 1297 | cmd->iter_num = cpu_to_le32(1); | 1325 | cmd->iter_num = cpu_to_le32(1); |
| 1298 | 1326 | ||
| 1299 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT && | ||
| 1300 | mvm->last_ebs_successful) { | ||
| 1301 | cmd->channel_opt[0].flags = | ||
| 1302 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1303 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1304 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1305 | cmd->channel_opt[0].non_ebs_ratio = | ||
| 1306 | cpu_to_le16(IWL_DENSE_EBS_SCAN_RATIO); | ||
| 1307 | cmd->channel_opt[1].flags = | ||
| 1308 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1309 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1310 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1311 | cmd->channel_opt[1].non_ebs_ratio = | ||
| 1312 | cpu_to_le16(IWL_SPARSE_EBS_SCAN_RATIO); | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | if (iwl_mvm_rrm_scan_needed(mvm)) | 1327 | if (iwl_mvm_rrm_scan_needed(mvm)) |
| 1316 | cmd->scan_flags |= | 1328 | cmd->scan_flags |= |
| 1317 | cpu_to_le32(IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED); | 1329 | cpu_to_le32(IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED); |
| @@ -1386,6 +1398,22 @@ int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm, | |||
| 1386 | cmd->schedule[1].iterations = 0; | 1398 | cmd->schedule[1].iterations = 0; |
| 1387 | cmd->schedule[1].full_scan_mul = 0; | 1399 | cmd->schedule[1].full_scan_mul = 0; |
| 1388 | 1400 | ||
| 1401 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SINGLE_SCAN_EBS && | ||
| 1402 | mvm->last_ebs_successful) { | ||
| 1403 | cmd->channel_opt[0].flags = | ||
| 1404 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1405 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1406 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1407 | cmd->channel_opt[0].non_ebs_ratio = | ||
| 1408 | cpu_to_le16(IWL_DENSE_EBS_SCAN_RATIO); | ||
| 1409 | cmd->channel_opt[1].flags = | ||
| 1410 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1411 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1412 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1413 | cmd->channel_opt[1].non_ebs_ratio = | ||
| 1414 | cpu_to_le16(IWL_SPARSE_EBS_SCAN_RATIO); | ||
| 1415 | } | ||
| 1416 | |||
| 1389 | for (i = 1; i <= req->req.n_ssids; i++) | 1417 | for (i = 1; i <= req->req.n_ssids; i++) |
| 1390 | ssid_bitmap |= BIT(i); | 1418 | ssid_bitmap |= BIT(i); |
| 1391 | 1419 | ||
| @@ -1458,6 +1486,8 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm, | |||
| 1458 | 1486 | ||
| 1459 | if (iwl_mvm_scan_pass_all(mvm, req)) | 1487 | if (iwl_mvm_scan_pass_all(mvm, req)) |
| 1460 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL; | 1488 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL; |
| 1489 | else | ||
| 1490 | flags |= IWL_MVM_LMAC_SCAN_FLAG_MATCH; | ||
| 1461 | 1491 | ||
| 1462 | if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0) | 1492 | if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0) |
| 1463 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION; | 1493 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION; |
| @@ -1468,6 +1498,11 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm, | |||
| 1468 | if (req->n_ssids == 0) | 1498 | if (req->n_ssids == 0) |
| 1469 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE; | 1499 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE; |
| 1470 | 1500 | ||
| 1501 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
| 1502 | if (mvm->scan_iter_notif_enabled) | ||
| 1503 | flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE; | ||
| 1504 | #endif | ||
| 1505 | |||
| 1471 | cmd->scan_flags |= cpu_to_le32(flags); | 1506 | cmd->scan_flags |= cpu_to_le32(flags); |
| 1472 | 1507 | ||
| 1473 | cmd->flags = iwl_mvm_scan_rxon_flags(req->channels[0]->band); | 1508 | cmd->flags = iwl_mvm_scan_rxon_flags(req->channels[0]->band); |
| @@ -1484,6 +1519,22 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm, | |||
| 1484 | cmd->schedule[1].iterations = 0xff; | 1519 | cmd->schedule[1].iterations = 0xff; |
| 1485 | cmd->schedule[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER; | 1520 | cmd->schedule[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER; |
| 1486 | 1521 | ||
| 1522 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT && | ||
| 1523 | mvm->last_ebs_successful) { | ||
| 1524 | cmd->channel_opt[0].flags = | ||
| 1525 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1526 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1527 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1528 | cmd->channel_opt[0].non_ebs_ratio = | ||
| 1529 | cpu_to_le16(IWL_DENSE_EBS_SCAN_RATIO); | ||
| 1530 | cmd->channel_opt[1].flags = | ||
| 1531 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1532 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1533 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1534 | cmd->channel_opt[1].non_ebs_ratio = | ||
| 1535 | cpu_to_le16(IWL_SPARSE_EBS_SCAN_RATIO); | ||
| 1536 | } | ||
| 1537 | |||
| 1487 | iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels, | 1538 | iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels, |
| 1488 | ssid_bitmap, cmd); | 1539 | ssid_bitmap, cmd); |
| 1489 | 1540 | ||
| @@ -1632,10 +1683,10 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) | |||
| 1632 | 1683 | ||
| 1633 | band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; | 1684 | band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; |
| 1634 | for (i = 0; i < band->n_channels; i++, j++) | 1685 | for (i = 0; i < band->n_channels; i++, j++) |
| 1635 | scan_config->channel_array[j] = band->channels[i].center_freq; | 1686 | scan_config->channel_array[j] = band->channels[i].hw_value; |
| 1636 | band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; | 1687 | band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; |
| 1637 | for (i = 0; i < band->n_channels; i++, j++) | 1688 | for (i = 0; i < band->n_channels; i++, j++) |
| 1638 | scan_config->channel_array[j] = band->channels[i].center_freq; | 1689 | scan_config->channel_array[j] = band->channels[i].hw_value; |
| 1639 | 1690 | ||
| 1640 | cmd.data[0] = scan_config; | 1691 | cmd.data[0] = scan_config; |
| 1641 | cmd.len[0] = cmd_size; | 1692 | cmd.len[0] = cmd_size; |
| @@ -1812,6 +1863,13 @@ int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 1812 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL; | 1863 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL; |
| 1813 | 1864 | ||
| 1814 | cmd->general_flags = cpu_to_le32(flags); | 1865 | cmd->general_flags = cpu_to_le32(flags); |
| 1866 | |||
| 1867 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SINGLE_SCAN_EBS && | ||
| 1868 | mvm->last_ebs_successful) | ||
| 1869 | cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1870 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1871 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; | ||
| 1872 | |||
| 1815 | cmd->n_channels = req->req.n_channels; | 1873 | cmd->n_channels = req->req.n_channels; |
| 1816 | 1874 | ||
| 1817 | for (i = 0; i < req->req.n_ssids; i++) | 1875 | for (i = 0; i < req->req.n_ssids; i++) |
| @@ -1975,7 +2033,9 @@ int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm, | |||
| 1975 | notif->ebs_status == IWL_SCAN_EBS_SUCCESS ? | 2033 | notif->ebs_status == IWL_SCAN_EBS_SUCCESS ? |
| 1976 | "success" : "failed"); | 2034 | "success" : "failed"); |
| 1977 | 2035 | ||
| 1978 | mvm->last_ebs_successful = !notif->ebs_status; | 2036 | if (notif->ebs_status) |
| 2037 | mvm->last_ebs_successful = false; | ||
| 2038 | |||
| 1979 | mvm->scan_uid[uid_idx] = 0; | 2039 | mvm->scan_uid[uid_idx] = 0; |
| 1980 | 2040 | ||
| 1981 | if (!sched) { | 2041 | if (!sched) { |
| @@ -2008,10 +2068,14 @@ static bool iwl_scan_umac_done_check(struct iwl_notif_wait_data *notif_wait, | |||
| 2008 | 2068 | ||
| 2009 | /* | 2069 | /* |
| 2010 | * Clear scan uid of scans that was aborted from above and completed | 2070 | * Clear scan uid of scans that was aborted from above and completed |
| 2011 | * in FW so the RX handler does nothing. | 2071 | * in FW so the RX handler does nothing. Set last_ebs_successful here if |
| 2072 | * needed. | ||
| 2012 | */ | 2073 | */ |
| 2013 | scan_done->mvm->scan_uid[uid_idx] = 0; | 2074 | scan_done->mvm->scan_uid[uid_idx] = 0; |
| 2014 | 2075 | ||
| 2076 | if (notif->ebs_status) | ||
| 2077 | scan_done->mvm->last_ebs_successful = false; | ||
| 2078 | |||
| 2015 | return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type); | 2079 | return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type); |
| 2016 | } | 2080 | } |
| 2017 | 2081 | ||
