iwlwifi: mvm: don't update quota in firmware too often
authorJohannes Berg <johannes.berg@intel.com>
Mon, 8 Sep 2014 14:42:54 +0000 (16:42 +0200)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 14 Sep 2014 09:56:40 +0000 (12:56 +0300)
When updating quota in the firmware, it has to reset quite a bit
of internal state, which apparently can have an adverse impact on
its operation.

Avoid that by only updating the quota command when there are any
signification changes, i.e. added/removed bindings or changes in
quota that are bigger than 8 TU within a binding.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/iwlwifi/mvm/constants.h
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/quota.c

index cb48656..1181089 100644 (file)
@@ -87,5 +87,6 @@
 #define IWL_MVM_BT_COEX_CORUNNING              1
 #define IWL_MVM_BT_COEX_MPLUT                  1
 #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL       0
+#define IWL_MVM_QUOTA_THRESHOLD                        8
 
 #endif /* __MVM_CONSTANTS_H */
index 21d6060..23fd711 100644 (file)
@@ -454,6 +454,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
        for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
                RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
 
+       /* reset quota debouncing buffer - 0xff will yield invalid data */
+       memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd));
+
        /* Add auxiliary station for scanning */
        ret = iwl_mvm_add_aux_sta(mvm);
        if (ret)
index e292de9..f05b7d7 100644 (file)
@@ -709,6 +709,8 @@ struct iwl_mvm {
         */
        bool temperature_test;  /* Debug test temperature is enabled */
 
+       struct iwl_time_quota_cmd last_quota_cmd;
+
 #ifdef CONFIG_NL80211_TESTMODE
        u32 noa_duration;
        struct ieee80211_vif *noa_vif;
index 5fd502d..1eab2f2 100644 (file)
@@ -175,12 +175,14 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
                          struct ieee80211_vif *disabled_vif)
 {
        struct iwl_time_quota_cmd cmd = {};
-       int i, idx, ret, num_active_macs, quota, quota_rem, n_non_lowlat;
+       int i, idx, err, num_active_macs, quota, quota_rem, n_non_lowlat;
        struct iwl_mvm_quota_iterator_data data = {
                .n_interfaces = {},
                .colors = { -1, -1, -1, -1 },
                .disabled_vif = disabled_vif,
        };
+       struct iwl_time_quota_cmd *last = &mvm->last_quota_cmd;
+       bool send = false;
 
        lockdep_assert_held(&mvm->mutex);
 
@@ -293,15 +295,34 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
 
        /* check that we have non-zero quota for all valid bindings */
        for (i = 0; i < MAX_BINDINGS; i++) {
+               if (cmd.quotas[i].id_and_color != last->quotas[i].id_and_color)
+                       send = true;
+               if (cmd.quotas[i].max_duration != last->quotas[i].max_duration)
+                       send = true;
+               if (abs((int)le32_to_cpu(cmd.quotas[i].quota) -
+                       (int)le32_to_cpu(last->quotas[i].quota))
+                                               > IWL_MVM_QUOTA_THRESHOLD)
+                       send = true;
                if (cmd.quotas[i].id_and_color == cpu_to_le32(FW_CTXT_INVALID))
                        continue;
                WARN_ONCE(cmd.quotas[i].quota == 0,
                          "zero quota on binding %d\n", i);
        }
 
-       ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,
-                                  sizeof(cmd), &cmd);
-       if (ret)
-               IWL_ERR(mvm, "Failed to send quota: %d\n", ret);
-       return ret;
+       if (send) {
+               err = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,
+                                          sizeof(cmd), &cmd);
+       } else {
+               /* don't send a practically unchanged command, the firmware has
+                * to re-initialize a lot of state and that can have an adverse
+                * impact on it
+                */
+               err = 0;
+       }
+
+       if (err)
+               IWL_ERR(mvm, "Failed to send quota: %d\n", err);
+       else
+               mvm->last_quota_cmd = cmd;
+       return err;
 }