iwlwifi: mvm: fix firmware debug restart recording
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Wed, 29 Mar 2017 07:21:09 +0000 (10:21 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Apr 2018 17:48:20 +0000 (19:48 +0200)
[ Upstream commit addce854f164a68da9cb158e2e7e447705068549 ]

When we want to stop the recording of the firmware debug
and restart it later without reloading the firmware we
don't need to resend the configuration that comes with
host commands.
Sending those commands confused the hardware and led to
an NMI 0x66.

Change the flow as following:
* read the relevant registers (DBGC_IN_SAMPLE, DBGC_OUT_CTRL)
* clear those registers
* wait for the hardware to complete its write to the buffer
* get the data
* restore the value of those registers (to restart the
  recording)

For early start (where the configuration is already
compiled in the firmware), we don't need to set those
registers after the firmware has been loaded, but only
when we want to restart the recording without having
restarted the firmware.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/intel/iwlwifi/iwl-prph.h
drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c

index 406ef301b8ab8aedd8a1e8e93e8800d53872a233..da8234b762bfdd5f5f98cbabb5054c1f162f7ec2 100644 (file)
 #define MON_DMARB_RD_DATA_ADDR         (0xa03c5c)
 
 #define DBGC_IN_SAMPLE                 (0xa03c00)
+#define DBGC_OUT_CTRL                  (0xa03c0c)
 
 /* enable the ID buf for read */
 #define WFPM_PS_CTL_CLR                        0xA0300C
index 700d244df34b76acbbf2082e9c92770dc18a20a5..2642d8e477b822b272f9e776ad3140b5af644cd9 100644 (file)
@@ -914,14 +914,6 @@ int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
        return 0;
 }
 
-static inline void iwl_mvm_restart_early_start(struct iwl_mvm *mvm)
-{
-       if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
-               iwl_clear_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
-       else
-               iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 1);
-}
-
 int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
 {
        u8 *ptr;
@@ -935,10 +927,8 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
        /* EARLY START - firmware's configuration is hard coded */
        if ((!mvm->fw->dbg_conf_tlv[conf_id] ||
             !mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) &&
-           conf_id == FW_DBG_START_FROM_ALIVE) {
-               iwl_mvm_restart_early_start(mvm);
+           conf_id == FW_DBG_START_FROM_ALIVE)
                return 0;
-       }
 
        if (!mvm->fw->dbg_conf_tlv[conf_id])
                return -EINVAL;
index c60703e0c246731cc3976dbe03f1f6fabe76f028..ed9bf8c759b45bb50a00cc0f18c991aaf2008007 100644 (file)
@@ -1687,6 +1687,7 @@ void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
 static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
 {
        mvm->ucode_loaded = false;
+       mvm->fw_dbg_conf = FW_DBG_INVALID;
        iwl_trans_stop_device(mvm->trans);
 }
 
index 4d35deb628bcaae711851a7e4acaf158883b57f0..6d38eec3f9d3cb5e4f0d3909e72224c35f2538d0 100644 (file)
@@ -1118,21 +1118,37 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)
 
        mutex_lock(&mvm->mutex);
 
-       /* stop recording */
        if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
+               /* stop recording */
                iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
+
+               iwl_mvm_fw_error_dump(mvm);
+
+               /* start recording again if the firmware is not crashed */
+               if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
+                   mvm->fw->dbg_dest_tlv)
+                       iwl_clear_bits_prph(mvm->trans,
+                                           MON_BUFF_SAMPLE_CTL, 0x100);
        } else {
+               u32 in_sample = iwl_read_prph(mvm->trans, DBGC_IN_SAMPLE);
+               u32 out_ctrl = iwl_read_prph(mvm->trans, DBGC_OUT_CTRL);
+
+               /* stop recording */
                iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
-               /* wait before we collect the data till the DBGC stop */
                udelay(100);
-       }
+               iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0);
+               /* wait before we collect the data till the DBGC stop */
+               udelay(500);
 
-       iwl_mvm_fw_error_dump(mvm);
+               iwl_mvm_fw_error_dump(mvm);
 
-       /* start recording again if the firmware is not crashed */
-       WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) &&
-                    mvm->fw->dbg_dest_tlv &&
-                    iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf));
+               /* start recording again if the firmware is not crashed */
+               if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
+                   mvm->fw->dbg_dest_tlv) {
+                       iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, in_sample);
+                       iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, out_ctrl);
+               }
+       }
 
        mutex_unlock(&mvm->mutex);