iwlwifi: mvm: allow to configure the timeout for the Tx queues
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 19 Mar 2015 18:04:51 +0000 (20:04 +0200)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Mon, 30 Mar 2015 05:57:16 +0000 (08:57 +0300)
Sometimes we will want to configure the timeouts for the
Tx queues based on the vif type. Allow to do that using the
trigger mechanism.

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/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/utils.c

index 37b38a585dd182f8fa1c44256f4a16ecc008d3df..46cbae8f821d6adc91b0ae8d0f9efa363ec972eb 100644 (file)
@@ -250,6 +250,8 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
  * @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.
+ * @FW_DBG_TRIGGER_TXQ_TIMERS: configures the timers for the Tx queue hang
+ *     detection.
  */
 enum iwl_fw_dbg_trigger {
        FW_DBG_TRIGGER_INVALID = 0,
@@ -261,6 +263,7 @@ enum iwl_fw_dbg_trigger {
        FW_DB_TRIGGER_RESERVED,
        FW_DBG_TRIGGER_STATS,
        FW_DBG_TRIGGER_RSSI,
+       FW_DBG_TRIGGER_TXQ_TIMERS,
 
        /* must be last */
        FW_DBG_TRIGGER_MAX,
index 60f3f86904fba1db781ef9c4db2fcad957652861..0cfc66d1aef2cdef20698446f3d2a947ac34569f 100644 (file)
@@ -578,6 +578,29 @@ struct iwl_fw_dbg_trigger_low_rssi {
        __le32 rssi;
 } __packed;
 
+/**
+ * struct iwl_fw_dbg_trigger_txq_timer - configures the Tx queue's timer
+ * @command_queue: timeout for the command queue in ms
+ * @bss: timeout for the queues of a BSS (except for TDLS queues) in ms
+ * @softap: timeout for the queues of a softAP in ms
+ * @p2p_go: timeout for the queues of a P2P GO in ms
+ * @p2p_client: timeout for the queues of a P2P client in ms
+ * @p2p_device: timeout for the queues of a P2P device in ms
+ * @ibss: timeout for the queues of an IBSS in ms
+ * @tdls: timeout for the queues of a TDLS station in ms
+ */
+struct iwl_fw_dbg_trigger_txq_timer {
+       __le32 command_queue;
+       __le32 bss;
+       __le32 softap;
+       __le32 p2p_go;
+       __le32 p2p_client;
+       __le32 p2p_device;
+       __le32 ibss;
+       __le32 tdls;
+       __le32 reserved[4];
+} __packed;
+
 /**
  * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
  * @id: conf id
index 581b3b8f29f9b6d7460b98eeb9ee54e3b9612c35..09f0124db76ec116c38ea205d9e9d1ee9522c047 100644 (file)
@@ -470,9 +470,8 @@ exit_fail:
 
 int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
-       unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
-                                       mvm->cfg->base_params->wd_timeout :
-                                       IWL_WATCHDOG_DISABLED;
+       unsigned int wdg_timeout =
+               iwl_mvm_get_wd_timeout(mvm, vif, false, false);
        u32 ac;
        int ret;
 
index 91c74d4f07541908072320f70d14c2d237cba96a..3513f27c888f35e6d641c34f6b7f714e446e4861 100644 (file)
@@ -1480,7 +1480,9 @@ void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm);
 int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
                                struct iwl_fw_dbg_trigger_tlv *trigger,
                                const char *str, size_t len);
-
+unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
+                                   struct ieee80211_vif *vif,
+                                   bool tdls, bool cmd_q);
 static inline bool
 iwl_fw_dbg_trigger_vif_match(struct iwl_fw_dbg_trigger_tlv *trig,
                             struct ieee80211_vif *vif)
index 91361be3ecd86b3d930e6b403b7e751fc263e44e..388886ce419dcc8de15ddb17a584dba0e5d88b33 100644 (file)
@@ -488,8 +488,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 
        /* Set a short watchdog for the command queue */
        trans_cfg.cmd_q_wdg_timeout =
-               iwlmvm_mod_params.tfd_q_hang_detect ? IWL_DEF_WD_TIMEOUT :
-                                                     IWL_WATCHDOG_DISABLED;
+               iwl_mvm_get_wd_timeout(mvm, NULL, false, true);
 
        snprintf(mvm->hw->wiphy->fw_version,
                 sizeof(mvm->hw->wiphy->fw_version),
index 9bf512bdbbd6460ec5d61c4827d99199e37b48d2..231e7dd6c8f0af1f8bc5a3ed6826cc524d331838 100644 (file)
@@ -209,9 +209,8 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm,
 {
        unsigned long used_hw_queues;
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-       unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
-                                       mvm->cfg->base_params->wd_timeout :
-                                       IWL_WATCHDOG_DISABLED;
+       unsigned int wdg_timeout =
+               iwl_mvm_get_wd_timeout(mvm, NULL, true, false);
        u32 ac;
 
        lockdep_assert_held(&mvm->mutex);
@@ -981,9 +980,8 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 {
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
-       unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
-                                       mvm->cfg->base_params->wd_timeout :
-                                       IWL_WATCHDOG_DISABLED;
+       unsigned int wdg_timeout =
+               iwl_mvm_get_wd_timeout(mvm, vif, sta->tdls, false);
        int queue, fifo, ret;
        u16 ssn;
 
index 435faee0a28eee1d674d95f07fc934baef2e13b0..593a810fe53ed056736c0ed63b5aca743426c156 100644 (file)
@@ -921,3 +921,47 @@ struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
 
        return bss_iter_data.vif;
 }
+
+unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
+                                   struct ieee80211_vif *vif,
+                                   bool tdls, bool cmd_q)
+{
+       struct iwl_fw_dbg_trigger_tlv *trigger;
+       struct iwl_fw_dbg_trigger_txq_timer *txq_timer;
+       unsigned int default_timeout =
+               cmd_q ? IWL_DEF_WD_TIMEOUT : mvm->cfg->base_params->wd_timeout;
+
+       if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS))
+               return iwlmvm_mod_params.tfd_q_hang_detect ?
+                       default_timeout : IWL_WATCHDOG_DISABLED;
+
+       trigger = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS);
+       txq_timer = (void *)trigger->data;
+
+       if (tdls)
+               return le32_to_cpu(txq_timer->tdls);
+
+       if (cmd_q)
+               return le32_to_cpu(txq_timer->command_queue);
+
+       if (WARN_ON(!vif))
+               return default_timeout;
+
+       switch (ieee80211_vif_type_p2p(vif)) {
+       case NL80211_IFTYPE_ADHOC:
+               return le32_to_cpu(txq_timer->ibss);
+       case NL80211_IFTYPE_STATION:
+               return le32_to_cpu(txq_timer->bss);
+       case NL80211_IFTYPE_AP:
+               return le32_to_cpu(txq_timer->softap);
+       case NL80211_IFTYPE_P2P_CLIENT:
+               return le32_to_cpu(txq_timer->p2p_client);
+       case NL80211_IFTYPE_P2P_GO:
+               return le32_to_cpu(txq_timer->p2p_go);
+       case NL80211_IFTYPE_P2P_DEVICE:
+               return le32_to_cpu(txq_timer->p2p_device);
+       default:
+               WARN_ON(1);
+               return mvm->cfg->base_params->wd_timeout;
+       }
+}