|
@@ -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;
|
|
|
|
|
- quota_rem = 0;
|
|
|
|
|
- if (num_active_macs) {
|
|
|
|
|
- quota = IWL_MVM_MAX_QUOTA / num_active_macs;
|
|
|
|
|
- quota_rem = IWL_MVM_MAX_QUOTA % num_active_macs;
|
|
|
|
|
|
|
+ n_non_lowlat = num_active_macs;
|
|
|
|
|
+
|
|
|
|
|
+ if (data.n_low_latency_bindings == 1) {
|
|
|
|
|
+ for (i = 0; i < MAX_BINDINGS; i++) {
|
|
|
|
|
+ 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]);
|