aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/quota.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-12-18 09:56:28 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-02-03 15:23:35 -0500
commit6ca40d6eae3e36068157412ceb9ddf1f2d53d1c8 (patch)
tree8d77da577f6345963e23f738d3337f019f03f81f /drivers/net/wireless/iwlwifi/mvm/quota.c
parente03f9bef2f9de4295df91a235c6b521dd64ef655 (diff)
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>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/quota.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/quota.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index ce5db6c4ef7e..0d2185b89d95 100644
--- a/drivers/net/wireless/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/iwlwifi/mvm/quota.c
@@ -65,9 +65,14 @@
65#include "fw-api.h" 65#include "fw-api.h"
66#include "mvm.h" 66#include "mvm.h"
67 67
68#define QUOTA_100 IWL_MVM_MAX_QUOTA
69#define QUOTA_LOWLAT_MIN ((QUOTA_100 * IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT) / 100)
70
68struct iwl_mvm_quota_iterator_data { 71struct iwl_mvm_quota_iterator_data {
69 int n_interfaces[MAX_BINDINGS]; 72 int n_interfaces[MAX_BINDINGS];
70 int colors[MAX_BINDINGS]; 73 int colors[MAX_BINDINGS];
74 int low_latency[MAX_BINDINGS];
75 int n_low_latency_bindings;
71 struct ieee80211_vif *new_vif; 76 struct ieee80211_vif *new_vif;
72}; 77};
73 78
@@ -107,22 +112,29 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
107 switch (vif->type) { 112 switch (vif->type) {
108 case NL80211_IFTYPE_STATION: 113 case NL80211_IFTYPE_STATION:
109 if (vif->bss_conf.assoc) 114 if (vif->bss_conf.assoc)
110 data->n_interfaces[id]++; 115 break;
111 break; 116 return;
112 case NL80211_IFTYPE_AP: 117 case NL80211_IFTYPE_AP:
113 case NL80211_IFTYPE_ADHOC: 118 case NL80211_IFTYPE_ADHOC:
114 if (mvmvif->ap_ibss_active) 119 if (mvmvif->ap_ibss_active)
115 data->n_interfaces[id]++; 120 break;
116 break; 121 return;
117 case NL80211_IFTYPE_MONITOR: 122 case NL80211_IFTYPE_MONITOR:
118 if (mvmvif->monitor_active) 123 if (mvmvif->monitor_active)
119 data->n_interfaces[id]++; 124 break;
120 break; 125 return;
121 case NL80211_IFTYPE_P2P_DEVICE: 126 case NL80211_IFTYPE_P2P_DEVICE:
122 break; 127 return;
123 default: 128 default:
124 WARN_ON_ONCE(1); 129 WARN_ON_ONCE(1);
125 break; 130 return;
131 }
132
133 data->n_interfaces[id]++;
134
135 if (iwl_mvm_vif_low_latency(mvmvif) && !data->low_latency[id]) {
136 data->n_low_latency_bindings++;
137 data->low_latency[id] = true;
126 } 138 }
127} 139}
128 140
@@ -162,7 +174,7 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
162int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) 174int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
163{ 175{
164 struct iwl_time_quota_cmd cmd = {}; 176 struct iwl_time_quota_cmd cmd = {};
165 int i, idx, ret, num_active_macs, quota, quota_rem; 177 int i, idx, ret, num_active_macs, quota, quota_rem, n_non_lowlat;
166 struct iwl_mvm_quota_iterator_data data = { 178 struct iwl_mvm_quota_iterator_data data = {
167 .n_interfaces = {}, 179 .n_interfaces = {},
168 .colors = { -1, -1, -1, -1 }, 180 .colors = { -1, -1, -1, -1 },
@@ -197,11 +209,30 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
197 num_active_macs += data.n_interfaces[i]; 209 num_active_macs += data.n_interfaces[i];
198 } 210 }
199 211
200 quota = 0; 212 n_non_lowlat = num_active_macs;
201 quota_rem = 0; 213
202 if (num_active_macs) { 214 if (data.n_low_latency_bindings == 1) {
203 quota = IWL_MVM_MAX_QUOTA / num_active_macs; 215 for (i = 0; i < MAX_BINDINGS; i++) {
204 quota_rem = IWL_MVM_MAX_QUOTA % num_active_macs; 216 if (data.low_latency[i]) {
217 n_non_lowlat -= data.n_interfaces[i];
218 break;
219 }
220 }
221 if (n_non_lowlat) {
222 quota = (QUOTA_100 - QUOTA_LOWLAT_MIN) / n_non_lowlat;
223 quota_rem = QUOTA_100 - n_non_lowlat * quota -
224 QUOTA_LOWLAT_MIN;
225 } else {
226 quota = QUOTA_100;
227 quota_rem = 0;
228 }
229 } else if (num_active_macs) {
230 quota = QUOTA_100 / num_active_macs;
231 quota_rem = QUOTA_100 % num_active_macs;
232 } else {
233 /* values don't really matter - won't be used */
234 quota = 0;
235 quota_rem = 0;
205 } 236 }
206 237
207 for (idx = 0, i = 0; i < MAX_BINDINGS; i++) { 238 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)
214 if (data.n_interfaces[i] <= 0) { 245 if (data.n_interfaces[i] <= 0) {
215 cmd.quotas[idx].quota = cpu_to_le32(0); 246 cmd.quotas[idx].quota = cpu_to_le32(0);
216 cmd.quotas[idx].max_duration = cpu_to_le32(0); 247 cmd.quotas[idx].max_duration = cpu_to_le32(0);
248 } else if (data.n_low_latency_bindings == 1 && n_non_lowlat &&
249 data.low_latency[i]) {
250 cmd.quotas[idx].quota = cpu_to_le32(QUOTA_LOWLAT_MIN);
251 cmd.quotas[idx].max_duration = cpu_to_le32(0);
217 } else { 252 } else {
218 cmd.quotas[idx].quota = 253 cmd.quotas[idx].quota =
219 cpu_to_le32(quota * data.n_interfaces[i]); 254 cpu_to_le32(quota * data.n_interfaces[i]);