iwlwifi: mvm: add trigger for firmware dump upon TDLS events
authorGolan Ben-Ami <golan.ben.ami@intel.com>
Sun, 23 Aug 2015 14:57:33 +0000 (17:57 +0300)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 26 Nov 2015 14:38:50 +0000 (16:38 +0200)
This will allow to catch different TDLS events and get the
firmware data when they occur.
Add empty TX_LATENCY trigger on the way to avoid mismatch
with trees in which this trigger is implemented.

Signed-off-by: Golan Ben-Ami <golan.ben.ami@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h
drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

index eedd0d874759567e5e0963d7e660f0646cdc8101..ce656650dd474567072169a2e4960c0af31d94f9 100644 (file)
@@ -1323,6 +1323,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
                sizeof(struct iwl_fw_dbg_trigger_time_event);
        trigger_tlv_sz[FW_DBG_TRIGGER_BA] =
                sizeof(struct iwl_fw_dbg_trigger_ba);
+       trigger_tlv_sz[FW_DBG_TRIGGER_TDLS] =
+               sizeof(struct iwl_fw_dbg_trigger_tdls);
 
        for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) {
                if (pieces->dbg_trigger_tlv[i]) {
index 9dbe19cbb4dd7233c57277fb91907d0b199dff04..73bcf29d30cc1175508bf90882562d787a17b3da 100644 (file)
@@ -288,6 +288,9 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
  * @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related
  *     events.
  * @FW_DBG_TRIGGER_BA: trigger log collection upon BlockAck related events.
+ * @FW_DBG_TX_LATENCY: trigger log collection when the tx latency goes above a
+ *     threshold.
+ * @FW_DBG_TDLS: trigger log collection upon TDLS related events.
  */
 enum iwl_fw_dbg_trigger {
        FW_DBG_TRIGGER_INVALID = 0,
@@ -302,6 +305,8 @@ enum iwl_fw_dbg_trigger {
        FW_DBG_TRIGGER_TXQ_TIMERS,
        FW_DBG_TRIGGER_TIME_EVENT,
        FW_DBG_TRIGGER_BA,
+       FW_DBG_TRIGGER_TX_LATENCY,
+       FW_DBG_TRIGGER_TDLS,
 
        /* must be last */
        FW_DBG_TRIGGER_MAX,
index 6aeecebe9c765e11a865e383dc7d9a39e197a550..e08319a3ed1b6838463dcd50df8c9e32baa5983e 100644 (file)
@@ -724,6 +724,19 @@ struct iwl_fw_dbg_trigger_ba {
        __le16 frame_timeout;
 } __packed;
 
+/**
+ * struct iwl_fw_dbg_trigger_tdls - configures trigger for TDLS events.
+ * @action_bitmap: the TDLS action to trigger the collection upon
+ * @peer_mode: trigger on specific peer or all
+ * @peer: the TDLS peer to trigger the collection on
+ */
+struct iwl_fw_dbg_trigger_tdls {
+       u8 action_bitmap;
+       u8 peer_mode;
+       u8 peer[ETH_ALEN];
+       u8 reserved[4];
+} __packed;
+
 /**
  * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
  * @id: conf id
index e88afac51c5d69fe5d6c8f4e032cdcf95f48a168..f570c71aeb2a649c9884c27cc6d5522430038551 100644 (file)
@@ -2699,6 +2699,34 @@ static void iwl_mvm_check_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
 }
 
+static void
+iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm,
+                          struct ieee80211_vif *vif, u8 *peer_addr,
+                          enum nl80211_tdls_operation action)
+{
+       struct iwl_fw_dbg_trigger_tlv *trig;
+       struct iwl_fw_dbg_trigger_tdls *tdls_trig;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TDLS))
+               return;
+
+       trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TDLS);
+       tdls_trig = (void *)trig->data;
+       if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
+               return;
+
+       if (!(tdls_trig->action_bitmap & BIT(action)))
+               return;
+
+       if (tdls_trig->peer_mode &&
+           memcmp(tdls_trig->peer, peer_addr, ETH_ALEN) != 0)
+               return;
+
+       iwl_mvm_fw_dbg_collect_trig(mvm, trig,
+                                   "TDLS event occurred, peer %pM, action %d",
+                                   peer_addr, action);
+}
+
 static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                                 struct ieee80211_vif *vif,
                                 struct ieee80211_sta *sta,
@@ -2749,8 +2777,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                }
 
                ret = iwl_mvm_add_sta(mvm, vif, sta);
-               if (sta->tdls && ret == 0)
+               if (sta->tdls && ret == 0) {
                        iwl_mvm_recalc_tdls_state(mvm, vif, true);
+                       iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
+                                                  NL80211_TDLS_SETUP);
+               }
        } else if (old_state == IEEE80211_STA_NONE &&
                   new_state == IEEE80211_STA_AUTH) {
                /*
@@ -2774,6 +2805,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                if (iwl_mvm_phy_ctx_count(mvm) > 1)
                        iwl_mvm_teardown_tdls_peers(mvm);
 
+               if (sta->tdls)
+                       iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
+                                                  NL80211_TDLS_ENABLE_LINK);
+
                /* enable beacon filtering */
                WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
                ret = 0;
@@ -2791,8 +2826,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
        } else if (old_state == IEEE80211_STA_NONE &&
                   new_state == IEEE80211_STA_NOTEXIST) {
                ret = iwl_mvm_rm_sta(mvm, vif, sta);
-               if (sta->tdls)
+               if (sta->tdls) {
                        iwl_mvm_recalc_tdls_state(mvm, vif, false);
+                       iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
+                                                  NL80211_TDLS_DISABLE_LINK);
+               }
        } else {
                ret = -EIO;
        }