iwlwifi: mvm: reserve bandwidth for low-latency interface

If there is/are interface(s) in low-latency mode, reserve a
percentage (currently 64%) of the quota for that binding to
improve the quality of service for those interfaces. However,
if there's more than one binding that has low-latency, then
give up and don't reserve, we can't allocate more than 100%.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This commit is contained in:
Johannes Berg 2013-12-18 15:56:28 +01:00 committed by Emmanuel Grumbach
parent e03f9bef2f
commit 6ca40d6eae
2 changed files with 50 additions and 14 deletions

View File

@ -78,5 +78,6 @@
#define IWL_MVM_PS_SNOOZE_INTERVAL 25 #define IWL_MVM_PS_SNOOZE_INTERVAL 25
#define IWL_MVM_PS_SNOOZE_WINDOW 50 #define IWL_MVM_PS_SNOOZE_WINDOW 50
#define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25 #define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25
#define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT 64
#endif /* __MVM_CONSTANTS_H */ #endif /* __MVM_CONSTANTS_H */

View File

@ -65,9 +65,14 @@
#include "fw-api.h" #include "fw-api.h"
#include "mvm.h" #include "mvm.h"
#define QUOTA_100 IWL_MVM_MAX_QUOTA
#define QUOTA_LOWLAT_MIN ((QUOTA_100 * IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT) / 100)
struct iwl_mvm_quota_iterator_data { struct iwl_mvm_quota_iterator_data {
int n_interfaces[MAX_BINDINGS]; int n_interfaces[MAX_BINDINGS];
int colors[MAX_BINDINGS]; int colors[MAX_BINDINGS];
int low_latency[MAX_BINDINGS];
int n_low_latency_bindings;
struct ieee80211_vif *new_vif; struct ieee80211_vif *new_vif;
}; };
@ -107,22 +112,29 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
if (vif->bss_conf.assoc) if (vif->bss_conf.assoc)
data->n_interfaces[id]++; break;
break; return;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
if (mvmvif->ap_ibss_active) if (mvmvif->ap_ibss_active)
data->n_interfaces[id]++; break;
break; return;
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
if (mvmvif->monitor_active) if (mvmvif->monitor_active)
data->n_interfaces[id]++; break;
break; return;
case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_P2P_DEVICE:
break; return;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
break; return;
}
data->n_interfaces[id]++;
if (iwl_mvm_vif_low_latency(mvmvif) && !data->low_latency[id]) {
data->n_low_latency_bindings++;
data->low_latency[id] = true;
} }
} }
@ -162,7 +174,7 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
{ {
struct iwl_time_quota_cmd cmd = {}; struct iwl_time_quota_cmd cmd = {};
int i, idx, ret, num_active_macs, quota, quota_rem; int i, idx, ret, num_active_macs, quota, quota_rem, n_non_lowlat;
struct iwl_mvm_quota_iterator_data data = { struct iwl_mvm_quota_iterator_data data = {
.n_interfaces = {}, .n_interfaces = {},
.colors = { -1, -1, -1, -1 }, .colors = { -1, -1, -1, -1 },
@ -197,11 +209,30 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
num_active_macs += data.n_interfaces[i]; num_active_macs += data.n_interfaces[i];
} }
quota = 0; n_non_lowlat = num_active_macs;
quota_rem = 0;
if (num_active_macs) { if (data.n_low_latency_bindings == 1) {
quota = IWL_MVM_MAX_QUOTA / num_active_macs; for (i = 0; i < MAX_BINDINGS; i++) {
quota_rem = IWL_MVM_MAX_QUOTA % num_active_macs; if (data.low_latency[i]) {
n_non_lowlat -= data.n_interfaces[i];
break;
}
}
if (n_non_lowlat) {
quota = (QUOTA_100 - QUOTA_LOWLAT_MIN) / n_non_lowlat;
quota_rem = QUOTA_100 - n_non_lowlat * quota -
QUOTA_LOWLAT_MIN;
} else {
quota = QUOTA_100;
quota_rem = 0;
}
} else if (num_active_macs) {
quota = QUOTA_100 / num_active_macs;
quota_rem = QUOTA_100 % num_active_macs;
} else {
/* values don't really matter - won't be used */
quota = 0;
quota_rem = 0;
} }
for (idx = 0, i = 0; i < MAX_BINDINGS; i++) { for (idx = 0, i = 0; i < MAX_BINDINGS; i++) {
@ -214,6 +245,10 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
if (data.n_interfaces[i] <= 0) { if (data.n_interfaces[i] <= 0) {
cmd.quotas[idx].quota = cpu_to_le32(0); cmd.quotas[idx].quota = cpu_to_le32(0);
cmd.quotas[idx].max_duration = cpu_to_le32(0); cmd.quotas[idx].max_duration = cpu_to_le32(0);
} else if (data.n_low_latency_bindings == 1 && n_non_lowlat &&
data.low_latency[i]) {
cmd.quotas[idx].quota = cpu_to_le32(QUOTA_LOWLAT_MIN);
cmd.quotas[idx].max_duration = cpu_to_le32(0);
} else { } else {
cmd.quotas[idx].quota = cmd.quotas[idx].quota =
cpu_to_le32(quota * data.n_interfaces[i]); cpu_to_le32(quota * data.n_interfaces[i]);