iwlwifi: dbg: support debug recording suspend resume command
authorShahar S Matityahu <shahar.s.matityahu@intel.com>
Sun, 19 May 2019 07:52:59 +0000 (10:52 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 6 Sep 2019 12:31:12 +0000 (15:31 +0300)
Support the new DBGC_SUSPEND_RESUME command to change the recording state.

Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/dbg.h
drivers/net/wireless/intel/iwlwifi/fw/file.h
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/ops.c

index 988584973aba759412537282aa6605e45406ba9d..b627c31d06ed04203c9d3de8c86e2a1c85377ab2 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -80,6 +80,13 @@ enum iwl_debug_cmds {
         * &struct iwl_dbg_mem_access_rsp
         */
        UMAC_RD_WR = 0x1,
+       /**
+        * @DBGC_SUSPEND_RESUME:
+        * DBGC suspend/resume commad. Uses a single dword as data:
+        * 0 - resume DBGC recording
+        * 1 - suspend DBGC recording
+        */
+       DBGC_SUSPEND_RESUME = 0x7,
        /**
         * @MFU_ASSERT_DUMP_NTF:
         * &struct iwl_mfu_assert_dump_notif
@@ -102,6 +109,16 @@ enum {
        FW_ERR_FATAL = 0xFF
 };
 
+/** enum iwl_dbg_suspend_resume_cmds - dbgc suspend resume operations
+ * dbgc suspend resume command operations
+ * @DBGC_RESUME_CMD: resume dbgc recording
+ * @DBGC_SUSPEND_CMD: stop dbgc recording
+ */
+enum iwl_dbg_suspend_resume_cmds {
+       DBGC_RESUME_CMD,
+       DBGC_SUSPEND_CMD,
+};
+
 /**
  * struct iwl_error_resp - FW error indication
  * ( REPLY_ERROR = 0x2 )
@@ -380,4 +397,13 @@ struct iwl_ldbg_config_cmd {
        }; /* LDBG_CFG_BODY_API_U_VER_2 (partially) */
 } __packed; /* LDBG_CFG_CMD_API_S_VER_2 */
 
+/**
+ * struct iwl_dbg_suspend_resume_cmd - dbgc suspend resume command
+ * @operation: suspend or resume operation, uses
+ *     &enum iwl_dbg_suspend_resume_cmds
+ */
+struct iwl_dbg_suspend_resume_cmd {
+       __le32 operation;
+} __packed;
+
 #endif /* __iwl_fw_api_debug_h__ */
index 9ccaecc104746578d378b8f559cf59a904ec8008..34f4cda3b0902fd33e849fc83efdd96ec687ebc2 100644 (file)
@@ -2372,7 +2372,10 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
                goto out;
        }
 
-       iwl_fw_dbg_stop_recording(fwrt->trans, &params);
+       if (iwl_fw_dbg_stop_restart_recording(fwrt, &params, true)) {
+               IWL_ERR(fwrt, "Failed to stop DBGC recording, aborting dump\n");
+               goto out;
+       }
 
        IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection start\n");
        if (fwrt->trans->dbg.ini_valid)
@@ -2381,7 +2384,7 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
                iwl_fw_error_dump(fwrt);
        IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection done\n");
 
-       iwl_fw_dbg_restart_recording(fwrt, &params);
+       iwl_fw_dbg_stop_restart_recording(fwrt, &params, false);
 
 out:
        clear_bit(wk_idx, &fwrt->dump.active_wks);
@@ -2870,7 +2873,7 @@ void iwl_fw_dbg_stop_sync(struct iwl_fw_runtime *fwrt)
        for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++)
                iwl_fw_dbg_collect_sync(fwrt, i);
 
-       iwl_fw_dbg_stop_recording(fwrt->trans, NULL);
+       iwl_fw_dbg_stop_restart_recording(fwrt, NULL, true);
 }
 IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_sync);
 
@@ -2938,8 +2941,24 @@ void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt)
 }
 IWL_EXPORT_SYMBOL(iwl_fw_error_print_fseq_regs);
 
-static void _iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
-                                      struct iwl_fw_dbg_params *params)
+static int iwl_fw_dbg_suspend_resume_hcmd(struct iwl_trans *trans, bool suspend)
+{
+       struct iwl_dbg_suspend_resume_cmd cmd = {
+               .operation = suspend ?
+                       cpu_to_le32(DBGC_SUSPEND_CMD) :
+                       cpu_to_le32(DBGC_RESUME_CMD),
+       };
+       struct iwl_host_cmd hcmd = {
+               .id = WIDE_ID(DEBUG_GROUP, DBGC_SUSPEND_RESUME),
+               .data[0] = &cmd,
+               .len[0] = sizeof(cmd),
+       };
+
+       return iwl_trans_send_cmd(trans, &hcmd);
+}
+
+static void iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
+                                     struct iwl_fw_dbg_params *params)
 {
        if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
                iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
@@ -2957,37 +2976,13 @@ static void _iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
         */
        usleep_range(700, 1000);
        iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-       trans->dbg.rec_on = false;
-#endif
-}
-
-void iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
-                              struct iwl_fw_dbg_params *params)
-{
-       /* if the FW crashed or not debug monitor cfg was given, there is
-        * no point in stopping
-        */
-       if (test_bit(STATUS_FW_ERROR, &trans->status) ||
-           (!trans->dbg.dest_tlv &&
-            trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
-               return;
-
-       if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
-               IWL_ERR(trans,
-                       "WRT: unsupported device family %d for debug stop recording\n",
-                       trans->cfg->device_family);
-               return;
-       }
-       _iwl_fw_dbg_stop_recording(trans, params);
 }
-IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_recording);
 
-static void _iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
-                                         struct iwl_fw_dbg_params *params)
+static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
+                                       struct iwl_fw_dbg_params *params)
 {
-       if (WARN_ON(!params))
-               return;
+       if (!params)
+               return -EIO;
 
        if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
                iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
@@ -2997,28 +2992,40 @@ static void _iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
                iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
                iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
        }
+
+       return 0;
 }
 
-void iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt,
-                                 struct iwl_fw_dbg_params *params)
+int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
+                                     struct iwl_fw_dbg_params *params,
+                                     bool stop)
 {
+       int ret = 0;
+
        /* if the FW crashed or not debug monitor cfg was given, there is
-        * no point in restarting
+        * no point in changing the recording state
         */
        if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status) ||
            (!fwrt->trans->dbg.dest_tlv &&
             fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
-               return;
+               return 0;
 
-       if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
-               IWL_ERR(fwrt,
-                       "WRT: unsupported device family %d for debug restart recording\n",
-                       fwrt->trans->cfg->device_family);
-               return;
-       }
-       _iwl_fw_dbg_restart_recording(fwrt->trans, params);
+       if (fw_has_capa(&fwrt->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP))
+               ret = iwl_fw_dbg_suspend_resume_hcmd(fwrt->trans, stop);
+       else if (stop)
+               iwl_fw_dbg_stop_recording(fwrt->trans, params);
+       else
+               ret = iwl_fw_dbg_restart_recording(fwrt->trans, params);
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-       iwl_fw_set_dbg_rec_on(fwrt);
+       if (!ret) {
+               if (stop)
+                       fwrt->trans->dbg.rec_on = false;
+               else
+                       iwl_fw_set_dbg_rec_on(fwrt);
+       }
 #endif
+
+       return ret;
 }
-IWL_EXPORT_SYMBOL(iwl_fw_dbg_restart_recording);
+IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_restart_recording);
index 5582a11f7c891fb87ecbcc780aec25326442f787..461331703ea6cc2f66422d78d397705b91d579ae 100644 (file)
@@ -262,12 +262,9 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
        _iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev),         \
                                        iwl_fw_dbg_get_trigger((fwrt)->fw,\
                                                               (trig)))
-
-void iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
-                              struct iwl_fw_dbg_params *params);
-
-void iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt,
-                                 struct iwl_fw_dbg_params *params);
+int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
+                                     struct iwl_fw_dbg_params *params,
+                                     bool stop);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt)
index 0c38e7392b6145a53bccb6b0311c6fabbc6bf1d4..ea2b3d77f84845da62abbdf770b70bc4e6c8482c 100644 (file)
@@ -465,6 +465,7 @@ enum iwl_ucode_tlv_capa {
        IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT              = (__force iwl_ucode_tlv_capa_t)88,
        IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT      = (__force iwl_ucode_tlv_capa_t)89,
        IWL_UCODE_TLV_CAPA_CSI_REPORTING                = (__force iwl_ucode_tlv_capa_t)90,
+       IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP  = (__force iwl_ucode_tlv_capa_t)92,
 
        /* set 3 */
        IWL_UCODE_TLV_CAPA_MLME_OFFLOAD                 = (__force iwl_ucode_tlv_capa_t)96,
index cec40855a6413b5cb56924aceb99fad9b726a1f0..3a8a0c43cb6ee5f0a88bfafe0dd7dfedb725d7dd 100644 (file)
@@ -1083,7 +1083,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
         * recording automatically.
         */
        if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_9000)
-               iwl_fw_dbg_stop_recording(mvm->trans, NULL);
+               iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true);
 
        /* must be last -- this switches firmware state */
        ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
index 722e427d534cadb11a5539dcca2634f1bf7aa130..bf0b9ee05c44ee1dd278e09546c3755cbfdc0dec 100644 (file)
@@ -465,6 +465,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
  * Access is done through binary search
  */
 static const struct iwl_hcmd_names iwl_mvm_debug_names[] = {
+       HCMD_NAME(DBGC_SUSPEND_RESUME),
        HCMD_NAME(MFU_ASSERT_DUMP_NTF),
 };