iwlwifi: mvm: add trigger for firmware dump upon MLME failures
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Tue, 10 Feb 2015 12:29:48 +0000 (14:29 +0200)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 2 Apr 2015 06:29:12 +0000 (09:29 +0300)
This will allow to catch failures in MLME and get the
firmware data when this happens.

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

index 46cbae8f821d6adc91b0ae8d0f9efa363ec972eb..8b926ece0d3a46859f81d2c310e7512381e61269 100644 (file)
@@ -246,7 +246,7 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
  * @FW_DBG_TRIGGER_CHANNEL_SWITCH: trigger log collection upon channel switch.
  * @FW_DBG_TRIGGER_FW_NOTIF: trigger log collection when the firmware sends a
  *     command response or a notification.
- * @FW_DB_TRIGGER_RESERVED: reserved
+ * @FW_DBG_TRIGGER_MLME: trigger log collection upon MLME event.
  * @FW_DBG_TRIGGER_STATS: trigger log collection upon statistics threshold.
  * @FW_DBG_TRIGGER_RSSI: trigger log collection when the rssi of the beacon
  *     goes below a threshold.
@@ -260,7 +260,7 @@ enum iwl_fw_dbg_trigger {
        FW_DBG_TRIGGER_MISSED_BEACONS,
        FW_DBG_TRIGGER_CHANNEL_SWITCH,
        FW_DBG_TRIGGER_FW_NOTIF,
-       FW_DB_TRIGGER_RESERVED,
+       FW_DBG_TRIGGER_MLME,
        FW_DBG_TRIGGER_STATS,
        FW_DBG_TRIGGER_RSSI,
        FW_DBG_TRIGGER_TXQ_TIMERS,
index 0cfc66d1aef2cdef20698446f3d2a947ac34569f..823938e3b7ef0766f257a422dccc3d5cb8105a17 100644 (file)
@@ -578,6 +578,41 @@ struct iwl_fw_dbg_trigger_low_rssi {
        __le32 rssi;
 } __packed;
 
+/**
+ * struct iwl_fw_dbg_trigger_mlme - configures trigger for mlme events
+ * @stop_auth_denied: number of denied authentication to collect
+ * @stop_auth_timeout: number of authentication timeout to collect
+ * @stop_rx_deauth: number of Rx deauth before to collect
+ * @stop_tx_deauth: number of Tx deauth before to collect
+ * @stop_assoc_denied: number of denied association to collect
+ * @stop_assoc_timeout: number of association timeout to collect
+ * @start_auth_denied: number of denied authentication to start recording
+ * @start_auth_timeout: number of authentication timeout to start recording
+ * @start_rx_deauth: number of Rx deauth to start recording
+ * @start_tx_deauth: number of Tx deauth to start recording
+ * @start_assoc_denied: number of denied association to start recording
+ * @start_assoc_timeout: number of association timeout to start recording
+ */
+struct iwl_fw_dbg_trigger_mlme {
+       u8 stop_auth_denied;
+       u8 stop_auth_timeout;
+       u8 stop_rx_deauth;
+       u8 stop_tx_deauth;
+
+       u8 stop_assoc_denied;
+       u8 stop_assoc_timeout;
+       __le16 reserved2;
+
+       u8 start_auth_denied;
+       u8 start_auth_timeout;
+       u8 start_rx_deauth;
+       u8 start_tx_deauth;
+
+       u8 start_assoc_denied;
+       u8 start_assoc_timeout;
+       __le16 reserved4;
+} __packed;
+
 /**
  * struct iwl_fw_dbg_trigger_txq_timer - configures the Tx queue's timer
  * @command_queue: timeout for the command queue in ms
index 810b6d317b24cb1462cd4ee068a6d7c9a5531374..fc73cc1bda0d2cf681ff1325ff560eb84a820ce1 100644 (file)
@@ -3956,6 +3956,69 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
        mutex_unlock(&mvm->mutex);
 }
 
+static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif,
+                                      const struct ieee80211_event *event)
+{
+#define CHECK_MLME_TRIGGER(_mvm, _trig, _buf, _cnt, _str...)   \
+       do {                                                    \
+               if ((_cnt) && --(_cnt))                         \
+                       break;                                  \
+               snprintf(_buf, sizeof(_buf), ##_str);           \
+               iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _buf,  \
+                                           sizeof(_buf));      \
+       } while (0)
+
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_fw_dbg_trigger_tlv *trig;
+       struct iwl_fw_dbg_trigger_mlme *trig_mlme;
+       char buf[32];
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME))
+               return;
+
+       if (event->u.mlme.status == MLME_SUCCESS)
+               return;
+
+       trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME);
+       trig_mlme = (void *)trig->data;
+       if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
+               return;
+
+       memset(buf, 0, sizeof(buf));
+
+       if (event->u.mlme.data == ASSOC_EVENT) {
+               if (event->u.mlme.status == MLME_DENIED)
+                       CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                          trig_mlme->stop_assoc_denied,
+                                          "DENIED ASSOC: reason %d",
+                                           event->u.mlme.reason);
+               else if (event->u.mlme.status == MLME_TIMEOUT)
+                       CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                          trig_mlme->stop_assoc_timeout,
+                                          "ASSOC TIMEOUT");
+       } else if (event->u.mlme.data == AUTH_EVENT) {
+               if (event->u.mlme.status == MLME_DENIED)
+                       CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                          trig_mlme->stop_auth_denied,
+                                          "DENIED AUTH: reason %d",
+                                          event->u.mlme.reason);
+               else if (event->u.mlme.status == MLME_TIMEOUT)
+                       CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                          trig_mlme->stop_auth_timeout,
+                                          "AUTH TIMEOUT");
+       } else if (event->u.mlme.data == DEAUTH_RX_EVENT) {
+               CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                  trig_mlme->stop_rx_deauth,
+                                  "DEAUTH RX %d", event->u.mlme.reason);
+       } else if (event->u.mlme.data == DEAUTH_TX_EVENT) {
+               CHECK_MLME_TRIGGER(mvm, trig, buf,
+                                  trig_mlme->stop_tx_deauth,
+                                  "DEAUTH TX %d", event->u.mlme.reason);
+       }
+#undef CHECK_MLME_TRIGGER
+}
+
 const struct ieee80211_ops iwl_mvm_hw_ops = {
        .tx = iwl_mvm_mac_tx,
        .ampdu_action = iwl_mvm_mac_ampdu_action,
@@ -4009,6 +4072,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
        .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
        .tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
 
+       .event_callback = iwl_mvm_mac_event_callback,
+
        CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
 
 #ifdef CONFIG_PM_SLEEP