iwlwifi: add support for triggering ini triggers
authorSara Sharon <sara.sharon@intel.com>
Thu, 21 Jun 2018 06:42:12 +0000 (09:42 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 14 Dec 2018 11:04:45 +0000 (13:04 +0200)
Add support for ini triggers.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/dbg.h
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c

index 58771e2..b17298b 100644 (file)
@@ -1329,10 +1329,10 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
 }
 IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc);
 
-int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
-                      enum iwl_fw_dbg_trigger trig,
-                      const char *str, size_t len,
-                      struct iwl_fw_dbg_trigger_tlv *trigger)
+int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
+                       enum iwl_fw_dbg_trigger trig,
+                       const char *str, size_t len,
+                       struct iwl_fw_dbg_trigger_tlv *trigger)
 {
        struct iwl_fw_dump_desc *desc;
        unsigned int delay = 0;
@@ -1367,6 +1367,47 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
 
        return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay);
 }
+IWL_EXPORT_SYMBOL(_iwl_fw_dbg_collect);
+
+int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
+                      u32 id, const char *str, size_t len)
+{
+       struct iwl_fw_dump_desc *desc;
+       u32 occur, delay;
+
+       if (!fwrt->trans->ini_valid)
+               return _iwl_fw_dbg_collect(fwrt, id, str, len, NULL);
+
+       if (id == FW_DBG_TRIGGER_USER)
+               id = IWL_FW_TRIGGER_ID_USER_TRIGGER;
+
+       if (WARN_ON(!fwrt->dump.active_trigs[id].active))
+               return -EINVAL;
+
+       delay = le32_to_cpu(fwrt->dump.active_trigs[id].conf->ignore_consec);
+       occur = le32_to_cpu(fwrt->dump.active_trigs[id].conf->occurrences);
+       if (!occur)
+               return 0;
+
+       if (le32_to_cpu(fwrt->dump.active_trigs[id].conf->force_restart)) {
+               IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id);
+               iwl_force_nmi(fwrt->trans);
+               return 0;
+       }
+
+       desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC);
+       if (!desc)
+               return -ENOMEM;
+
+       occur--;
+       fwrt->dump.active_trigs[id].conf->occurrences = cpu_to_le32(occur);
+
+       desc->len = len;
+       desc->trig_desc.type = cpu_to_le32(id);
+       memcpy(desc->trig_desc.data, str, len);
+
+       return iwl_fw_dbg_collect_desc(fwrt, desc, true, delay);
+}
 IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect);
 
 int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
@@ -1395,8 +1436,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
                len = strlen(buf) + 1;
        }
 
-       ret = iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
-                                trigger);
+       ret = _iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len,
+                                 trigger);
 
        if (ret)
                return ret;
@@ -1668,6 +1709,12 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
                        active->conf = trig;
                }
 
+               /* Since zero means infinity - just set to -1 */
+               if (!le32_to_cpu(trig->occurrences))
+                       trig->occurrences = cpu_to_le32(-1);
+               if (!le32_to_cpu(trig->ignore_consec))
+                       trig->ignore_consec = cpu_to_le32(-1);
+
                iter += sizeof(*trig) +
                        le32_to_cpu(trig->num_regions) * sizeof(__le32);
 
index 324ee06..c14e461 100644 (file)
@@ -108,10 +108,12 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt);
 int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
                            const struct iwl_fw_dump_desc *desc,
                            bool monitor_only, unsigned int delay);
+int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
+                       enum iwl_fw_dbg_trigger trig,
+                       const char *str, size_t len,
+                       struct iwl_fw_dbg_trigger_tlv *trigger);
 int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt,
-                      enum iwl_fw_dbg_trigger trig,
-                      const char *str, size_t len,
-                      struct iwl_fw_dbg_trigger_tlv *trigger);
+                      u32 id, const char *str, size_t len);
 int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt,
                            struct iwl_fw_dbg_trigger_tlv *trigger,
                            const char *fmt, ...) __printf(3, 4);
@@ -213,6 +215,37 @@ _iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt,
        _iwl_fw_dbg_trigger_on((fwrt), (wdev), (id));           \
 })
 
+static inline bool
+_iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt,
+                      const enum iwl_fw_dbg_trigger id)
+{
+       struct iwl_fw_ini_active_triggers *trig = &fwrt->dump.active_trigs[id];
+       u32 ms;
+
+       if (!fwrt->trans->ini_valid)
+               return false;
+
+       if (!trig || !trig->active)
+               return false;
+
+       ms = le32_to_cpu(trig->conf->ignore_consec);
+       if (ms)
+               ms /= USEC_PER_MSEC;
+
+       if (iwl_fw_dbg_no_trig_window(fwrt, id, ms)) {
+               IWL_WARN(fwrt, "Trigger %d fired in no-collect window\n", id);
+               return false;
+       }
+
+       return true;
+}
+
+#define iwl_fw_ini_trigger_on(fwrt, wdev, id) ({               \
+       BUILD_BUG_ON(!__builtin_constant_p(id));                \
+       BUILD_BUG_ON((id) >= IWL_FW_TRIGGER_ID_NUM);            \
+       _iwl_fw_ini_trigger_on((fwrt), (wdev), (id));           \
+})
+
 static inline void
 _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
                                struct wireless_dev *wdev,
index 204ad5b..77845de 100644 (file)
@@ -138,7 +138,7 @@ struct iwl_fw_runtime {
                u8 conf;
 
                /* ts of the beginning of a non-collect fw dbg data period */
-               unsigned long non_collect_ts_start[FW_DBG_TRIGGER_MAX - 1];
+               unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM - 1];
                u32 *d3_debug_data;
                struct iwl_fw_ini_active_regs active_regs[IWL_FW_INI_MAX_REGION_ID];
                struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM];
index 3b6b3d8..52c361a 100644 (file)
@@ -1284,7 +1284,7 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
                return 0;
 
        iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
-                          (count - 1), NULL);
+                          (count - 1));
 
        iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);