aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/quota.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/quota.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/quota.c100
1 files changed, 79 insertions, 21 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index ce5db6c4ef7e..35e86e06dffd 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,39 @@ 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 }
222
223 if (data.n_low_latency_bindings == 1 && n_non_lowlat) {
224 /*
225 * Reserve quota for the low latency binding in case that
226 * there are several data bindings but only a single
227 * low latency one. Split the rest of the quota equally
228 * between the other data interfaces.
229 */
230 quota = (QUOTA_100 - QUOTA_LOWLAT_MIN) / n_non_lowlat;
231 quota_rem = QUOTA_100 - n_non_lowlat * quota -
232 QUOTA_LOWLAT_MIN;
233 } else if (num_active_macs) {
234 /*
235 * There are 0 or more than 1 low latency bindings, or all the
236 * data interfaces belong to the single low latency binding.
237 * Split the quota equally between the data interfaces.
238 */
239 quota = QUOTA_100 / num_active_macs;
240 quota_rem = QUOTA_100 % num_active_macs;
241 } else {
242 /* values don't really matter - won't be used */
243 quota = 0;
244 quota_rem = 0;
205 } 245 }
206 246
207 for (idx = 0, i = 0; i < MAX_BINDINGS; i++) { 247 for (idx = 0, i = 0; i < MAX_BINDINGS; i++) {
@@ -211,19 +251,37 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
211 cmd.quotas[idx].id_and_color = 251 cmd.quotas[idx].id_and_color =
212 cpu_to_le32(FW_CMD_ID_AND_COLOR(i, data.colors[i])); 252 cpu_to_le32(FW_CMD_ID_AND_COLOR(i, data.colors[i]));
213 253
214 if (data.n_interfaces[i] <= 0) { 254 if (data.n_interfaces[i] <= 0)
215 cmd.quotas[idx].quota = cpu_to_le32(0); 255 cmd.quotas[idx].quota = cpu_to_le32(0);
216 cmd.quotas[idx].max_duration = cpu_to_le32(0); 256 else if (data.n_low_latency_bindings == 1 && n_non_lowlat &&
217 } else { 257 data.low_latency[i])
258 /*
259 * There is more than one binding, but only one of the
260 * bindings is in low latency. For this case, allocate
261 * the minimal required quota for the low latency
262 * binding.
263 */
264 cmd.quotas[idx].quota = cpu_to_le32(QUOTA_LOWLAT_MIN);
265 else
218 cmd.quotas[idx].quota = 266 cmd.quotas[idx].quota =
219 cpu_to_le32(quota * data.n_interfaces[i]); 267 cpu_to_le32(quota * data.n_interfaces[i]);
220 cmd.quotas[idx].max_duration = cpu_to_le32(0); 268
221 } 269 WARN_ONCE(le32_to_cpu(cmd.quotas[idx].quota) > QUOTA_100,
270 "Binding=%d, quota=%u > max=%u\n",
271 idx, le32_to_cpu(cmd.quotas[idx].quota), QUOTA_100);
272
273 cmd.quotas[idx].max_duration = cpu_to_le32(0);
274
222 idx++; 275 idx++;
223 } 276 }
224 277
225 /* Give the remainder of the session to the first binding */ 278 /* Give the remainder of the session to the first data binding */
226 le32_add_cpu(&cmd.quotas[0].quota, quota_rem); 279 for (i = 0; i < MAX_BINDINGS; i++) {
280 if (le32_to_cpu(cmd.quotas[i].quota) != 0) {
281 le32_add_cpu(&cmd.quotas[i].quota, quota_rem);
282 break;
283 }
284 }
227 285
228 iwl_mvm_adjust_quota_for_noa(mvm, &cmd); 286 iwl_mvm_adjust_quota_for_noa(mvm, &cmd);
229 287