iwlwifi: add support for triggering ini triggers

Add support for ini triggers.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
Sara Sharon 2018-06-21 09:42:12 +03:00 committed by Luca Coelho
parent 7a14c23dcd
commit fe1b7d6c28
4 changed files with 91 additions and 11 deletions

View 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);

View 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,

View 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];

View 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);