diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2015-03-25 16:40:47 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2015-04-02 02:29:13 -0400 |
commit | 874c174eb9950a62032a7c90c4a23947a2bb863d (patch) | |
tree | 2c0f62d3c2223d1adf5204b48383f1c58c2b2a70 /drivers/net/wireless | |
parent | 5d4f929e3d0c09838677a116ffd168d9d519ada7 (diff) |
iwlwifi: mvm: add trigger for time events
This will allow to collect data when a time event
notifcation with a certain id and action is coming from
the firmware. This can be very useful to debug various
flows.
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-drv.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fw-file.h | 16 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/time-event.c | 42 |
4 files changed, 63 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 7783ac8761c4..e7475629c44e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -1237,6 +1237,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
1237 | sizeof(struct iwl_fw_dbg_trigger_low_rssi); | 1237 | sizeof(struct iwl_fw_dbg_trigger_low_rssi); |
1238 | trigger_tlv_sz[FW_DBG_TRIGGER_TXQ_TIMERS] = | 1238 | trigger_tlv_sz[FW_DBG_TRIGGER_TXQ_TIMERS] = |
1239 | sizeof(struct iwl_fw_dbg_trigger_txq_timer); | 1239 | sizeof(struct iwl_fw_dbg_trigger_txq_timer); |
1240 | trigger_tlv_sz[FW_DBG_TRIGGER_TIME_EVENT] = | ||
1241 | sizeof(struct iwl_fw_dbg_trigger_time_event); | ||
1240 | 1242 | ||
1241 | for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) { | 1243 | for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) { |
1242 | if (pieces->dbg_trigger_tlv[i]) { | 1244 | if (pieces->dbg_trigger_tlv[i]) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h index 37652857b8d0..251bf8dc4a12 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | |||
@@ -252,6 +252,8 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data) | |||
252 | * goes below a threshold. | 252 | * goes below a threshold. |
253 | * @FW_DBG_TRIGGER_TXQ_TIMERS: configures the timers for the Tx queue hang | 253 | * @FW_DBG_TRIGGER_TXQ_TIMERS: configures the timers for the Tx queue hang |
254 | * detection. | 254 | * detection. |
255 | * @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related | ||
256 | * events. | ||
255 | */ | 257 | */ |
256 | enum iwl_fw_dbg_trigger { | 258 | enum iwl_fw_dbg_trigger { |
257 | FW_DBG_TRIGGER_INVALID = 0, | 259 | FW_DBG_TRIGGER_INVALID = 0, |
@@ -264,6 +266,7 @@ enum iwl_fw_dbg_trigger { | |||
264 | FW_DBG_TRIGGER_STATS, | 266 | FW_DBG_TRIGGER_STATS, |
265 | FW_DBG_TRIGGER_RSSI, | 267 | FW_DBG_TRIGGER_RSSI, |
266 | FW_DBG_TRIGGER_TXQ_TIMERS, | 268 | FW_DBG_TRIGGER_TXQ_TIMERS, |
269 | FW_DBG_TRIGGER_TIME_EVENT, | ||
267 | 270 | ||
268 | /* must be last */ | 271 | /* must be last */ |
269 | FW_DBG_TRIGGER_MAX, | 272 | FW_DBG_TRIGGER_MAX, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index cc789cb3c052..ee149482061f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -637,6 +637,22 @@ struct iwl_fw_dbg_trigger_txq_timer { | |||
637 | } __packed; | 637 | } __packed; |
638 | 638 | ||
639 | /** | 639 | /** |
640 | * struct iwl_fw_dbg_trigger_time_event - configures a time event trigger | ||
641 | * time_Events: a list of tuples <id, action_bitmap>. The driver will issue a | ||
642 | * trigger each time a time event notification that relates to time event | ||
643 | * id with one of the actions in the bitmap is received and | ||
644 | * BIT(notif->status) is set in status_bitmap. | ||
645 | * | ||
646 | */ | ||
647 | struct iwl_fw_dbg_trigger_time_event { | ||
648 | struct { | ||
649 | __le32 id; | ||
650 | __le32 action_bitmap; | ||
651 | __le32 status_bitmap; | ||
652 | } __packed time_events[16]; | ||
653 | } __packed; | ||
654 | |||
655 | /** | ||
640 | * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration. | 656 | * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration. |
641 | * @id: conf id | 657 | * @id: conf id |
642 | * @usniffer: should the uSniffer image be used | 658 | * @usniffer: should the uSniffer image be used |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index bd519597eb2d..647822366fe5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -226,6 +226,44 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm, | |||
226 | iwl_mvm_te_clear_data(mvm, te_data); | 226 | iwl_mvm_te_clear_data(mvm, te_data); |
227 | } | 227 | } |
228 | 228 | ||
229 | static void iwl_mvm_te_check_trigger(struct iwl_mvm *mvm, | ||
230 | struct iwl_time_event_notif *notif, | ||
231 | struct iwl_mvm_time_event_data *te_data) | ||
232 | { | ||
233 | struct iwl_fw_dbg_trigger_tlv *trig; | ||
234 | struct iwl_fw_dbg_trigger_time_event *te_trig; | ||
235 | int i; | ||
236 | |||
237 | if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT)) | ||
238 | return; | ||
239 | |||
240 | trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT); | ||
241 | te_trig = (void *)trig->data; | ||
242 | |||
243 | if (!iwl_fw_dbg_trigger_check_stop(mvm, te_data->vif, trig)) | ||
244 | return; | ||
245 | |||
246 | for (i = 0; i < ARRAY_SIZE(te_trig->time_events); i++) { | ||
247 | u32 trig_te_id = le32_to_cpu(te_trig->time_events[i].id); | ||
248 | u32 trig_action_bitmap = | ||
249 | le32_to_cpu(te_trig->time_events[i].action_bitmap); | ||
250 | u32 trig_status_bitmap = | ||
251 | le32_to_cpu(te_trig->time_events[i].status_bitmap); | ||
252 | |||
253 | if (trig_te_id != te_data->id || | ||
254 | !(trig_action_bitmap & le32_to_cpu(notif->action)) || | ||
255 | !(trig_status_bitmap & BIT(le32_to_cpu(notif->status)))) | ||
256 | continue; | ||
257 | |||
258 | iwl_mvm_fw_dbg_collect_trig(mvm, trig, | ||
259 | "Time event %d Action 0x%x received status: %d", | ||
260 | te_data->id, | ||
261 | le32_to_cpu(notif->action), | ||
262 | le32_to_cpu(notif->status)); | ||
263 | break; | ||
264 | } | ||
265 | } | ||
266 | |||
229 | /* | 267 | /* |
230 | * Handles a FW notification for an event that is known to the driver. | 268 | * Handles a FW notification for an event that is known to the driver. |
231 | * | 269 | * |
@@ -243,6 +281,8 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
243 | le32_to_cpu(notif->unique_id), | 281 | le32_to_cpu(notif->unique_id), |
244 | le32_to_cpu(notif->action)); | 282 | le32_to_cpu(notif->action)); |
245 | 283 | ||
284 | iwl_mvm_te_check_trigger(mvm, notif, te_data); | ||
285 | |||
246 | /* | 286 | /* |
247 | * The FW sends the start/end time event notifications even for events | 287 | * The FW sends the start/end time event notifications even for events |
248 | * that it fails to schedule. This is indicated in the status field of | 288 | * that it fails to schedule. This is indicated in the status field of |
@@ -324,6 +364,8 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm, | |||
324 | if (!aux_roc_te) /* Not a Aux ROC time event */ | 364 | if (!aux_roc_te) /* Not a Aux ROC time event */ |
325 | return -EINVAL; | 365 | return -EINVAL; |
326 | 366 | ||
367 | iwl_mvm_te_check_trigger(mvm, notif, te_data); | ||
368 | |||
327 | if (!le32_to_cpu(notif->status)) { | 369 | if (!le32_to_cpu(notif->status)) { |
328 | IWL_DEBUG_TE(mvm, | 370 | IWL_DEBUG_TE(mvm, |
329 | "ERROR: Aux ROC Time Event %s notification failure\n", | 371 | "ERROR: Aux ROC Time Event %s notification failure\n", |