aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath10k/wmi.c
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-08-05 08:54:44 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2014-08-12 03:47:48 -0400
commit5c81c7fd62004be13a3c9345ca25607d14862cc4 (patch)
tree49826629326a55210f514427776fdc39fa8c51fb /drivers/net/wireless/ath/ath10k/wmi.c
parent9ff8b7247dd211158410af4bb5ebbc507182729f (diff)
ath10k: introduce a stricter scan state machine
This aims at fixing some rare scan bugs related to firmware reporting unexpected scan event sequences. One such bug was if spectral scan phyerr reporting prevented firmware from properly propagating scan events to host. This led to scan timeout. After that next scan would trigger scan completed event first (before scan started event) leading to ar->scan.in_progress and timeout timer states to be overwritten incorrectly and making the very next scan to hang forever. Reported-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/wmi.c')
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c143
1 files changed, 107 insertions, 36 deletions
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index f48f29563a4d..23acbadeb8fa 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -811,6 +811,94 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
811 return ret; 811 return ret;
812} 812}
813 813
814static void ath10k_wmi_event_scan_started(struct ath10k *ar)
815{
816 lockdep_assert_held(&ar->data_lock);
817
818 switch (ar->scan.state) {
819 case ATH10K_SCAN_IDLE:
820 case ATH10K_SCAN_RUNNING:
821 case ATH10K_SCAN_ABORTING:
822 ath10k_warn("received scan started event in an invalid scan state: %s (%d)\n",
823 ath10k_scan_state_str(ar->scan.state),
824 ar->scan.state);
825 break;
826 case ATH10K_SCAN_STARTING:
827 ar->scan.state = ATH10K_SCAN_RUNNING;
828
829 if (ar->scan.is_roc)
830 ieee80211_ready_on_channel(ar->hw);
831
832 complete(&ar->scan.started);
833 break;
834 }
835}
836
837static void ath10k_wmi_event_scan_completed(struct ath10k *ar)
838{
839 lockdep_assert_held(&ar->data_lock);
840
841 switch (ar->scan.state) {
842 case ATH10K_SCAN_IDLE:
843 case ATH10K_SCAN_STARTING:
844 /* One suspected reason scan can be completed while starting is
845 * if firmware fails to deliver all scan events to the host,
846 * e.g. when transport pipe is full. This has been observed
847 * with spectral scan phyerr events starving wmi transport
848 * pipe. In such case the "scan completed" event should be (and
849 * is) ignored by the host as it may be just firmware's scan
850 * state machine recovering.
851 */
852 ath10k_warn("received scan completed event in an invalid scan state: %s (%d)\n",
853 ath10k_scan_state_str(ar->scan.state),
854 ar->scan.state);
855 break;
856 case ATH10K_SCAN_RUNNING:
857 case ATH10K_SCAN_ABORTING:
858 __ath10k_scan_finish(ar);
859 break;
860 }
861}
862
863static void ath10k_wmi_event_scan_bss_chan(struct ath10k *ar)
864{
865 lockdep_assert_held(&ar->data_lock);
866
867 switch (ar->scan.state) {
868 case ATH10K_SCAN_IDLE:
869 case ATH10K_SCAN_STARTING:
870 ath10k_warn("received scan bss chan event in an invalid scan state: %s (%d)\n",
871 ath10k_scan_state_str(ar->scan.state),
872 ar->scan.state);
873 break;
874 case ATH10K_SCAN_RUNNING:
875 case ATH10K_SCAN_ABORTING:
876 ar->scan_channel = NULL;
877 break;
878 }
879}
880
881static void ath10k_wmi_event_scan_foreign_chan(struct ath10k *ar, u32 freq)
882{
883 lockdep_assert_held(&ar->data_lock);
884
885 switch (ar->scan.state) {
886 case ATH10K_SCAN_IDLE:
887 case ATH10K_SCAN_STARTING:
888 ath10k_warn("received scan foreign chan event in an invalid scan state: %s (%d)\n",
889 ath10k_scan_state_str(ar->scan.state),
890 ar->scan.state);
891 break;
892 case ATH10K_SCAN_RUNNING:
893 case ATH10K_SCAN_ABORTING:
894 ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq);
895
896 if (ar->scan.is_roc && ar->scan.roc_freq == freq)
897 complete(&ar->scan.on_channel);
898 break;
899 }
900}
901
814static const char * 902static const char *
815ath10k_wmi_event_scan_type_str(enum wmi_scan_event_type type, 903ath10k_wmi_event_scan_type_str(enum wmi_scan_event_type type,
816 enum wmi_scan_completion_reason reason) 904 enum wmi_scan_completion_reason reason)
@@ -864,54 +952,32 @@ static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
864 scan_id = __le32_to_cpu(event->scan_id); 952 scan_id = __le32_to_cpu(event->scan_id);
865 vdev_id = __le32_to_cpu(event->vdev_id); 953 vdev_id = __le32_to_cpu(event->vdev_id);
866 954
955 spin_lock_bh(&ar->data_lock);
956
867 ath10k_dbg(ATH10K_DBG_WMI, 957 ath10k_dbg(ATH10K_DBG_WMI,
868 "scan event %s type %d reason %d freq %d req_id %d " 958 "scan event %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n",
869 "scan_id %d vdev_id %d\n",
870 ath10k_wmi_event_scan_type_str(event_type, reason), 959 ath10k_wmi_event_scan_type_str(event_type, reason),
871 event_type, reason, freq, req_id, scan_id, vdev_id); 960 event_type, reason, freq, req_id, scan_id, vdev_id,
872 961 ath10k_scan_state_str(ar->scan.state), ar->scan.state);
873 spin_lock_bh(&ar->data_lock);
874 962
875 switch (event_type) { 963 switch (event_type) {
876 case WMI_SCAN_EVENT_STARTED: 964 case WMI_SCAN_EVENT_STARTED:
877 if (ar->scan.in_progress && ar->scan.is_roc) 965 ath10k_wmi_event_scan_started(ar);
878 ieee80211_ready_on_channel(ar->hw);
879
880 complete(&ar->scan.started);
881 break; 966 break;
882 case WMI_SCAN_EVENT_COMPLETED: 967 case WMI_SCAN_EVENT_COMPLETED:
883 ar->scan_channel = NULL; 968 ath10k_wmi_event_scan_completed(ar);
884 if (!ar->scan.in_progress) {
885 ath10k_warn("no scan requested, ignoring\n");
886 break;
887 }
888
889 if (ar->scan.is_roc) {
890 ath10k_offchan_tx_purge(ar);
891
892 if (!ar->scan.aborting)
893 ieee80211_remain_on_channel_expired(ar->hw);
894 } else {
895 ieee80211_scan_completed(ar->hw, ar->scan.aborting);
896 }
897
898 del_timer(&ar->scan.timeout);
899 complete_all(&ar->scan.completed);
900 ar->scan.in_progress = false;
901 break; 969 break;
902 case WMI_SCAN_EVENT_BSS_CHANNEL: 970 case WMI_SCAN_EVENT_BSS_CHANNEL:
903 ar->scan_channel = NULL; 971 ath10k_wmi_event_scan_bss_chan(ar);
904 break; 972 break;
905 case WMI_SCAN_EVENT_FOREIGN_CHANNEL: 973 case WMI_SCAN_EVENT_FOREIGN_CHANNEL:
906 ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq); 974 ath10k_wmi_event_scan_foreign_chan(ar, freq);
907 if (ar->scan.in_progress && ar->scan.is_roc && 975 break;
908 ar->scan.roc_freq == freq) { 976 case WMI_SCAN_EVENT_START_FAILED:
909 complete(&ar->scan.on_channel); 977 ath10k_warn("received scan start failure event\n");
910 }
911 break; 978 break;
912 case WMI_SCAN_EVENT_DEQUEUED: 979 case WMI_SCAN_EVENT_DEQUEUED:
913 case WMI_SCAN_EVENT_PREEMPTED: 980 case WMI_SCAN_EVENT_PREEMPTED:
914 case WMI_SCAN_EVENT_START_FAILED:
915 default: 981 default:
916 break; 982 break;
917 } 983 }
@@ -1171,9 +1237,14 @@ static void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
1171 1237
1172 spin_lock_bh(&ar->data_lock); 1238 spin_lock_bh(&ar->data_lock);
1173 1239
1174 if (!ar->scan.in_progress) { 1240 switch (ar->scan.state) {
1175 ath10k_warn("chan info event without a scan request?\n"); 1241 case ATH10K_SCAN_IDLE:
1242 case ATH10K_SCAN_STARTING:
1243 ath10k_warn("received chan info event without a scan request, ignoring\n");
1176 goto exit; 1244 goto exit;
1245 case ATH10K_SCAN_RUNNING:
1246 case ATH10K_SCAN_ABORTING:
1247 break;
1177 } 1248 }
1178 1249
1179 idx = freq_to_idx(ar, freq); 1250 idx = freq_to_idx(ar, freq);