iwlwifi: d3: read all FW CPUs error info
authorMordechay Goodstein <mordechay.goodstein@intel.com>
Fri, 31 Jan 2020 13:45:30 +0000 (15:45 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 3 Feb 2020 18:09:14 +0000 (20:09 +0200)
Continue the wakeup flow only if no FW CPUs have an error

If we don't check for error in all FW CPUs the driver can think
based on one CPU that the FW is operational and try to access
and send commands.

Also, handle the error_id endianness correctly as le32

Signed-off-by: Mordechay Goodstein <mordechay.goodstein@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/intel/iwlwifi/mvm/d3.c

index 8878409d2f07961ab1dde44631cb1f530efe45dc..22a32eb10f016a85aca40e520cedb7f02f48e134 100644 (file)
@@ -1897,27 +1897,55 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
                ieee80211_resume_disconnect(vif);
 }
 
-static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
-                                  struct ieee80211_vif *vif)
+static bool iwl_mvm_rt_status(struct iwl_trans *trans, u32 base, u32 *err_id)
 {
-       u32 base = mvm->trans->dbg.lmac_error_event_table[0];
        struct error_table_start {
                /* cf. struct iwl_error_event_table */
                u32 valid;
-               u32 error_id;
+               __le32 err_id;
        } err_info;
 
-       iwl_trans_read_mem_bytes(mvm->trans, base,
+       if (!base)
+               return false;
+
+       iwl_trans_read_mem_bytes(trans, base,
                                 &err_info, sizeof(err_info));
+       if (err_info.valid && err_id)
+               *err_id = le32_to_cpu(err_info.err_id);
 
-       if (err_info.valid &&
-           err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
-               struct cfg80211_wowlan_wakeup wakeup = {
-                       .rfkill_release = true,
-               };
-               ieee80211_report_wowlan_wakeup(vif, &wakeup, GFP_KERNEL);
+       return !!err_info.valid;
+}
+
+static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
+                                  struct ieee80211_vif *vif)
+{
+       u32 err_id;
+
+       /* check for lmac1 error */
+       if (iwl_mvm_rt_status(mvm->trans,
+                             mvm->trans->dbg.lmac_error_event_table[0],
+                             &err_id)) {
+               if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
+                       struct cfg80211_wowlan_wakeup wakeup = {
+                               .rfkill_release = true,
+                       };
+                       ieee80211_report_wowlan_wakeup(vif, &wakeup,
+                                                      GFP_KERNEL);
+               }
+               return true;
        }
-       return err_info.valid;
+
+       /* check if we have lmac2 set and check for error */
+       if (iwl_mvm_rt_status(mvm->trans,
+                             mvm->trans->dbg.lmac_error_event_table[1], NULL))
+               return true;
+
+       /* check for umac error */
+       if (iwl_mvm_rt_status(mvm->trans,
+                             mvm->trans->dbg.umac_error_event_table, NULL))
+               return true;
+
+       return false;
 }
 
 static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)