Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ath11k: reduce the wait time of 11d scan and hw scan while add interface

(cherry picked from commit 1f682dc9fb3790aa7ec27d3d122ff32b1eda1365 in wireless-next)

Currently ath11k will wait 11d scan complete while add interface in
ath11k_mac_op_add_interface(), when system resume without enable
wowlan, ath11k_mac_op_add_interface() is called for each resume, thus
it increase the resume time of system. And ath11k_mac_op_hw_scan()
after ath11k_mac_op_add_interface() also needs some time cost because
the previous 11d scan need more than 5 seconds when 6 GHz is enabled,
then the scan started event will indicated to ath11k after the 11d
scan completed.

While 11d scan/hw scan is running in firmware, if ath11k update channel
list to firmware by WMI_SCAN_CHAN_LIST_CMDID, then firmware will cancel
the current scan which is running, it lead the scan failed. The patch
commit 9dcf6808b253 ("ath11k: add 11d scan offload support") used
finish_11d_scan/finish_11d_ch_list/pending_11d to synchronize the 11d
scan/hw scan/channel list between ath11k/firmware/mac80211 and to avoid
the scan fail.

Add wait operation before ath11k update channel list, function
ath11k_reg_update_chan_list() will wait until the current 11d scan/hw
scan completed. And remove the wait operation of start 11d scan and
waiting channel list complete in hw scan. After these changes, resume
time cost reduce about 5 seconds and also hw scan time cost reduced
obviously, and scan failed not seen.

The 11d scan is sent to firmware only one time for each interface added
in mac.c, and it is moved after the 1st hw scan because 11d scan will
cost some time and thus leads the AP scan result update to UI delay.
Currently priority of ath11k's hw scan is WMI_SCAN_PRIORITY_LOW, and
priority of 11d scan in firmware is WMI_SCAN_PRIORITY_MEDIUM, then the
11d scan which sent after hw scan will cancel the hw scan in firmware,
so change the priority to WMI_SCAN_PRIORITY_MEDIUM for the hw scan which
is in front of the 11d scan, thus it will not happen scan cancel in
firmware.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3

Fixes: 9dcf6808b253 ("ath11k: add 11d scan offload support")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=215777
Cc: <stable@vger.kernel.org>
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220328035832.14122-1-quic_wgong@quicinc.com
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220427111619.9758-1-kvalo@kernel.org

authored by

Wen Gong and committed by
Kalle Valo
bb300130 4dd4e6f6

+84 -64
+1
drivers/net/wireless/ath/ath11k/core.c
··· 1288 1288 1289 1289 ieee80211_stop_queues(ar->hw); 1290 1290 ath11k_mac_drain_tx(ar); 1291 + complete(&ar->completed_11d_scan); 1291 1292 complete(&ar->scan.started); 1292 1293 complete(&ar->scan.completed); 1293 1294 complete(&ar->peer_assoc_done);
+10 -3
drivers/net/wireless/ath/ath11k/core.h
··· 38 38 39 39 extern unsigned int ath11k_frame_mode; 40 40 41 + #define ATH11K_SCAN_TIMEOUT_HZ (20 * HZ) 42 + 41 43 #define ATH11K_MON_TIMER_INTERVAL 10 42 44 43 45 enum ath11k_supported_bw { ··· 189 187 ATH11K_SCAN_STARTING, 190 188 ATH11K_SCAN_RUNNING, 191 189 ATH11K_SCAN_ABORTING, 190 + }; 191 + 192 + enum ath11k_11d_state { 193 + ATH11K_11D_IDLE, 194 + ATH11K_11D_PREPARING, 195 + ATH11K_11D_RUNNING, 192 196 }; 193 197 194 198 enum ath11k_dev_flags { ··· 615 607 bool dfs_block_radar_events; 616 608 struct ath11k_thermal thermal; 617 609 u32 vdev_id_11d_scan; 618 - struct completion finish_11d_scan; 619 - struct completion finish_11d_ch_list; 620 - bool pending_11d; 610 + struct completion completed_11d_scan; 611 + enum ath11k_11d_state state_11d; 621 612 bool regdom_set_by_user; 622 613 int hw_rate_code; 623 614 u8 twt_enabled;
+29 -42
drivers/net/wireless/ath/ath11k/mac.c
··· 3601 3601 if (ret) 3602 3602 goto exit; 3603 3603 3604 - /* Currently the pending_11d=true only happened 1 time while 3605 - * wlan interface up in ath11k_mac_11d_scan_start(), it is called by 3606 - * ath11k_mac_op_add_interface(), after wlan interface up, 3607 - * pending_11d=false always. 3608 - * If remove below wait, it always happened scan fail and lead connect 3609 - * fail while wlan interface up, because it has a 11d scan which is running 3610 - * in firmware, and lead this scan failed. 3611 - */ 3612 - if (ar->pending_11d) { 3613 - long time_left; 3614 - unsigned long timeout = 5 * HZ; 3615 - 3616 - if (ar->supports_6ghz) 3617 - timeout += 5 * HZ; 3618 - 3619 - time_left = wait_for_completion_timeout(&ar->finish_11d_ch_list, timeout); 3620 - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, 3621 - "mac wait 11d channel list time left %ld\n", time_left); 3622 - } 3623 - 3624 3604 memset(&arg, 0, sizeof(arg)); 3625 3605 ath11k_wmi_start_scan_init(ar, &arg); 3626 3606 arg.vdev_id = arvif->vdev_id; ··· 3666 3686 kfree(arg.extraie.ptr); 3667 3687 3668 3688 mutex_unlock(&ar->conf_mutex); 3689 + 3690 + if (ar->state_11d == ATH11K_11D_PREPARING) 3691 + ath11k_mac_11d_scan_start(ar, arvif->vdev_id); 3692 + 3669 3693 return ret; 3670 3694 } 3671 3695 ··· 5798 5814 5799 5815 /* TODO: Do we need to enable ANI? */ 5800 5816 5801 - ath11k_reg_update_chan_list(ar); 5817 + ath11k_reg_update_chan_list(ar, false); 5802 5818 5803 5819 ar->num_started_vdevs = 0; 5804 5820 ar->num_created_vdevs = 0; ··· 5864 5880 cancel_work_sync(&ar->regd_update_work); 5865 5881 cancel_work_sync(&ar->ab->update_11d_work); 5866 5882 cancel_work_sync(&ar->ab->rfkill_work); 5883 + 5884 + if (ar->state_11d == ATH11K_11D_PREPARING) { 5885 + ar->state_11d = ATH11K_11D_IDLE; 5886 + complete(&ar->completed_11d_scan); 5887 + } 5867 5888 5868 5889 spin_lock_bh(&ar->data_lock); 5869 5890 list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) { ··· 6040 6051 return false; 6041 6052 } 6042 6053 6043 - void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait) 6054 + void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id) 6044 6055 { 6045 6056 struct wmi_11d_scan_start_params param; 6046 6057 int ret; ··· 6068 6079 6069 6080 ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac start 11d scan\n"); 6070 6081 6071 - if (wait) 6072 - reinit_completion(&ar->finish_11d_scan); 6073 - 6074 6082 ret = ath11k_wmi_send_11d_scan_start_cmd(ar, &param); 6075 6083 if (ret) { 6076 6084 ath11k_warn(ar->ab, "failed to start 11d scan vdev %d ret: %d\n", 6077 6085 vdev_id, ret); 6078 6086 } else { 6079 6087 ar->vdev_id_11d_scan = vdev_id; 6080 - if (wait) { 6081 - ar->pending_11d = true; 6082 - ret = wait_for_completion_timeout(&ar->finish_11d_scan, 6083 - 5 * HZ); 6084 - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, 6085 - "mac 11d scan left time %d\n", ret); 6086 - 6087 - if (!ret) 6088 - ar->pending_11d = false; 6089 - } 6088 + if (ar->state_11d == ATH11K_11D_PREPARING) 6089 + ar->state_11d = ATH11K_11D_RUNNING; 6090 6090 } 6091 6091 6092 6092 fin: 6093 + if (ar->state_11d == ATH11K_11D_PREPARING) { 6094 + ar->state_11d = ATH11K_11D_IDLE; 6095 + complete(&ar->completed_11d_scan); 6096 + } 6097 + 6093 6098 mutex_unlock(&ar->ab->vdev_id_11d_lock); 6094 6099 } 6095 6100 ··· 6106 6123 vdev_id = ar->vdev_id_11d_scan; 6107 6124 6108 6125 ret = ath11k_wmi_send_11d_scan_stop_cmd(ar, vdev_id); 6109 - if (ret) 6126 + if (ret) { 6110 6127 ath11k_warn(ar->ab, 6111 6128 "failed to stopt 11d scan vdev %d ret: %d\n", 6112 6129 vdev_id, ret); 6113 - else 6130 + } else { 6114 6131 ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID; 6132 + ar->state_11d = ATH11K_11D_IDLE; 6133 + complete(&ar->completed_11d_scan); 6134 + } 6115 6135 } 6116 6136 mutex_unlock(&ar->ab->vdev_id_11d_lock); 6117 6137 } ··· 6310 6324 goto err_peer_del; 6311 6325 } 6312 6326 6313 - ath11k_mac_11d_scan_start(ar, arvif->vdev_id, true); 6314 - 6327 + if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map)) { 6328 + reinit_completion(&ar->completed_11d_scan); 6329 + ar->state_11d = ATH11K_11D_PREPARING; 6330 + } 6315 6331 break; 6316 6332 case WMI_VDEV_TYPE_MONITOR: 6317 6333 set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); ··· 7178 7190 } 7179 7191 7180 7192 if (arvif->vdev_type == WMI_VDEV_TYPE_STA) 7181 - ath11k_mac_11d_scan_start(ar, arvif->vdev_id, false); 7193 + ath11k_mac_11d_scan_start(ar, arvif->vdev_id); 7182 7194 7183 7195 mutex_unlock(&ar->conf_mutex); 7184 7196 } ··· 8659 8671 ar->monitor_vdev_id = -1; 8660 8672 clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); 8661 8673 ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID; 8662 - init_completion(&ar->finish_11d_scan); 8663 - init_completion(&ar->finish_11d_ch_list); 8674 + init_completion(&ar->completed_11d_scan); 8664 8675 } 8665 8676 8666 8677 return 0;
+1 -1
drivers/net/wireless/ath/ath11k/mac.h
··· 130 130 #define ATH11K_SCAN_11D_INTERVAL 600000 131 131 #define ATH11K_11D_INVALID_VDEV_ID 0xFFFF 132 132 133 - void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait); 133 + void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id); 134 134 void ath11k_mac_11d_scan_stop(struct ath11k *ar); 135 135 void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab); 136 136
+28 -15
drivers/net/wireless/ath/ath11k/reg.c
··· 102 102 ar->regdom_set_by_user = true; 103 103 } 104 104 105 - int ath11k_reg_update_chan_list(struct ath11k *ar) 105 + int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait) 106 106 { 107 107 struct ieee80211_supported_band **bands; 108 108 struct scan_chan_list_params *params; ··· 111 111 struct channel_param *ch; 112 112 enum nl80211_band band; 113 113 int num_channels = 0; 114 - int i, ret; 114 + int i, ret, left; 115 + 116 + if (wait && ar->state_11d != ATH11K_11D_IDLE) { 117 + left = wait_for_completion_timeout(&ar->completed_11d_scan, 118 + ATH11K_SCAN_TIMEOUT_HZ); 119 + if (!left) { 120 + ath11k_dbg(ar->ab, ATH11K_DBG_REG, 121 + "failed to receive 11d scan complete: timed out\n"); 122 + ar->state_11d = ATH11K_11D_IDLE; 123 + } 124 + ath11k_dbg(ar->ab, ATH11K_DBG_REG, 125 + "reg 11d scan wait left time %d\n", left); 126 + } 127 + 128 + if (wait && 129 + (ar->scan.state == ATH11K_SCAN_STARTING || 130 + ar->scan.state == ATH11K_SCAN_RUNNING)) { 131 + left = wait_for_completion_timeout(&ar->scan.completed, 132 + ATH11K_SCAN_TIMEOUT_HZ); 133 + if (!left) 134 + ath11k_dbg(ar->ab, ATH11K_DBG_REG, 135 + "failed to receive hw scan complete: timed out\n"); 136 + 137 + ath11k_dbg(ar->ab, ATH11K_DBG_REG, 138 + "reg hw scan wait left time %d\n", left); 139 + } 115 140 116 141 bands = hw->wiphy->bands; 117 142 for (band = 0; band < NUM_NL80211_BANDS; band++) { ··· 218 193 ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params); 219 194 kfree(params); 220 195 221 - if (ar->pending_11d) { 222 - complete(&ar->finish_11d_ch_list); 223 - ar->pending_11d = false; 224 - } 225 - 226 196 return ret; 227 197 } 228 198 ··· 283 263 goto err; 284 264 } 285 265 286 - if (ar->pending_11d) 287 - complete(&ar->finish_11d_scan); 288 - 289 266 rtnl_lock(); 290 267 wiphy_lock(ar->hw->wiphy); 291 - 292 - if (ar->pending_11d) 293 - reinit_completion(&ar->finish_11d_ch_list); 294 - 295 268 ret = regulatory_set_wiphy_regd_sync(ar->hw->wiphy, regd_copy); 296 269 wiphy_unlock(ar->hw->wiphy); 297 270 rtnl_unlock(); ··· 295 282 goto err; 296 283 297 284 if (ar->state == ATH11K_STATE_ON) { 298 - ret = ath11k_reg_update_chan_list(ar); 285 + ret = ath11k_reg_update_chan_list(ar, true); 299 286 if (ret) 300 287 goto err; 301 288 }
+1 -1
drivers/net/wireless/ath/ath11k/reg.h
··· 32 32 ath11k_reg_build_regd(struct ath11k_base *ab, 33 33 struct cur_regulatory_info *reg_info, bool intersect); 34 34 int ath11k_regd_update(struct ath11k *ar); 35 - int ath11k_reg_update_chan_list(struct ath11k *ar); 35 + int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait); 36 36 #endif
+14 -2
drivers/net/wireless/ath/ath11k/wmi.c
··· 2015 2015 { 2016 2016 /* setup commonly used values */ 2017 2017 arg->scan_req_id = 1; 2018 - arg->scan_priority = WMI_SCAN_PRIORITY_LOW; 2018 + if (ar->state_11d == ATH11K_11D_PREPARING) 2019 + arg->scan_priority = WMI_SCAN_PRIORITY_MEDIUM; 2020 + else 2021 + arg->scan_priority = WMI_SCAN_PRIORITY_LOW; 2019 2022 arg->dwell_time_active = 50; 2020 2023 arg->dwell_time_active_2g = 0; 2021 2024 arg->dwell_time_passive = 150; ··· 6353 6350 static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *skb) 6354 6351 { 6355 6352 const struct wmi_11d_new_cc_ev *ev; 6353 + struct ath11k *ar; 6354 + struct ath11k_pdev *pdev; 6356 6355 const void **tb; 6357 - int ret; 6356 + int ret, i; 6358 6357 6359 6358 tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); 6360 6359 if (IS_ERR(tb)) { ··· 6381 6376 ab->new_alpha2[1]); 6382 6377 6383 6378 kfree(tb); 6379 + 6380 + for (i = 0; i < ab->num_radios; i++) { 6381 + pdev = &ab->pdevs[i]; 6382 + ar = pdev->ar; 6383 + ar->state_11d = ATH11K_11D_IDLE; 6384 + complete(&ar->completed_11d_scan); 6385 + } 6384 6386 6385 6387 queue_work(ab->workqueue, &ab->update_11d_work); 6386 6388