[go: nahoru, domu]

18ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg/******************************************************************************
28ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
38ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * This file is provided under a dual BSD/GPLv2 license.  When using or
48ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * redistributing this file, you may do so under either license.
58ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
68ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * GPL LICENSE SUMMARY
78ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
851368bf792c79eb917694a4155d62f04359e3734Emmanuel Grumbach * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
98b4139dc9f2171f313fc703c08269f6f8a6f6fc4Johannes Berg * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
108ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
118ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * This program is free software; you can redistribute it and/or modify
128ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * it under the terms of version 2 of the GNU General Public License as
138ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * published by the Free Software Foundation.
148ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
158ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * This program is distributed in the hope that it will be useful, but
168ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * WITHOUT ANY WARRANTY; without even the implied warranty of
178ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
188ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * General Public License for more details.
198ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
208ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * You should have received a copy of the GNU General Public License
218ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * along with this program; if not, write to the Free Software
228ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
238ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * USA
248ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
258ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * The full GNU General Public License is included in this distribution
26410dc5aa5906ed49e2733b451a5287884e8a16dcEmmanuel Grumbach * in the file called COPYING.
278ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
288ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Contact Information:
298ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *  Intel Linux Wireless <ilw@linux.intel.com>
308ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
318ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
328ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * BSD LICENSE
338ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
3451368bf792c79eb917694a4155d62f04359e3734Emmanuel Grumbach * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
358b4139dc9f2171f313fc703c08269f6f8a6f6fc4Johannes Berg * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
368ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * All rights reserved.
378ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
388ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * Redistribution and use in source and binary forms, with or without
398ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * modification, are permitted provided that the following conditions
408ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * are met:
418ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
428ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *  * Redistributions of source code must retain the above copyright
438ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *    notice, this list of conditions and the following disclaimer.
448ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *  * Redistributions in binary form must reproduce the above copyright
458ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *    notice, this list of conditions and the following disclaimer in
468ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *    the documentation and/or other materials provided with the
478ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *    distribution.
488ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *  * Neither the name Intel Corporation nor the names of its
498ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *    contributors may be used to endorse or promote products derived
508ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *    from this software without specific prior written permission.
518ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
528ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
538ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
548ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
558ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
568ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
578ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
588ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
598ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
608ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
618ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
628ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
638ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *
648ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg *****************************************************************************/
658ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
668ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#include <net/mac80211.h>
678ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#include "fw-api.h"
688ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg#include "mvm.h"
698ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
706ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg#define QUOTA_100	IWL_MVM_MAX_QUOTA
716ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg#define QUOTA_LOWLAT_MIN ((QUOTA_100 * IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT) / 100)
726ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg
738ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergstruct iwl_mvm_quota_iterator_data {
748ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	int n_interfaces[MAX_BINDINGS];
758ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	int colors[MAX_BINDINGS];
766ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg	int low_latency[MAX_BINDINGS];
776ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg	int n_low_latency_bindings;
780166230c6c696d501a2d2616a30e295b71e39d43Johannes Berg	struct ieee80211_vif *disabled_vif;
798ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg};
808ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
818ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Bergstatic void iwl_mvm_quota_iterator(void *_data, u8 *mac,
828ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg				   struct ieee80211_vif *vif)
838ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{
848ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	struct iwl_mvm_quota_iterator_data *data = _data;
858ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
868ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	u16 id;
878ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
880166230c6c696d501a2d2616a30e295b71e39d43Johannes Berg	/* skip disabled interfaces here immediately */
890166230c6c696d501a2d2616a30e295b71e39d43Johannes Berg	if (vif == data->disabled_vif)
908ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		return;
918ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
928ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	if (!mvmvif->phy_ctxt)
938ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		return;
948ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
958ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	/* currently, PHY ID == binding ID */
968ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	id = mvmvif->phy_ctxt->id;
978ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
988ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	/* need at least one binding per PHY */
998ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	BUILD_BUG_ON(NUM_PHY_CTX > MAX_BINDINGS);
1008ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
1018ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	if (WARN_ON_ONCE(id >= MAX_BINDINGS))
1028ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		return;
1038ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
1048ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	switch (vif->type) {
1058ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	case NL80211_IFTYPE_STATION:
1068ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		if (vif->bss_conf.assoc)
1076ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg			break;
1086ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		return;
1098ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	case NL80211_IFTYPE_AP:
1105023d96616a1faf46656f8bb5545387d7cca9026Johannes Berg	case NL80211_IFTYPE_ADHOC:
1115023d96616a1faf46656f8bb5545387d7cca9026Johannes Berg		if (mvmvif->ap_ibss_active)
1126ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg			break;
1136ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		return;
1148ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	case NL80211_IFTYPE_MONITOR:
1151e1391ca43994b697b0145384797a078ce1e0ce7Ilan Peer		if (mvmvif->monitor_active)
1166ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg			break;
1176ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		return;
1188ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	case NL80211_IFTYPE_P2P_DEVICE:
1196ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		return;
1208ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	default:
1218ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		WARN_ON_ONCE(1);
1226ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		return;
1236ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg	}
1246ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg
12563faceb60b8e026d62db228ff04038e8089fa74aJohannes Berg	if (data->colors[id] < 0)
12663faceb60b8e026d62db228ff04038e8089fa74aJohannes Berg		data->colors[id] = mvmvif->phy_ctxt->color;
12763faceb60b8e026d62db228ff04038e8089fa74aJohannes Berg	else
12863faceb60b8e026d62db228ff04038e8089fa74aJohannes Berg		WARN_ON_ONCE(data->colors[id] != mvmvif->phy_ctxt->color);
12963faceb60b8e026d62db228ff04038e8089fa74aJohannes Berg
1306ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg	data->n_interfaces[id]++;
1316ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg
1326ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg	if (iwl_mvm_vif_low_latency(mvmvif) && !data->low_latency[id]) {
1336ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		data->n_low_latency_bindings++;
1346ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		data->low_latency[id] = true;
1358ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	}
1368ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg}
1378ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
138507cadf262fe67cd71e02247b240706be12f1042David Spinadelstatic void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
139507cadf262fe67cd71e02247b240706be12f1042David Spinadel					 struct iwl_time_quota_cmd *cmd)
140507cadf262fe67cd71e02247b240706be12f1042David Spinadel{
141507cadf262fe67cd71e02247b240706be12f1042David Spinadel#ifdef CONFIG_NL80211_TESTMODE
142507cadf262fe67cd71e02247b240706be12f1042David Spinadel	struct iwl_mvm_vif *mvmvif;
143507cadf262fe67cd71e02247b240706be12f1042David Spinadel	int i, phy_id = -1, beacon_int = 0;
144507cadf262fe67cd71e02247b240706be12f1042David Spinadel
145507cadf262fe67cd71e02247b240706be12f1042David Spinadel	if (!mvm->noa_duration || !mvm->noa_vif)
146507cadf262fe67cd71e02247b240706be12f1042David Spinadel		return;
147507cadf262fe67cd71e02247b240706be12f1042David Spinadel
148507cadf262fe67cd71e02247b240706be12f1042David Spinadel	mvmvif = iwl_mvm_vif_from_mac80211(mvm->noa_vif);
1495023d96616a1faf46656f8bb5545387d7cca9026Johannes Berg	if (!mvmvif->ap_ibss_active)
150507cadf262fe67cd71e02247b240706be12f1042David Spinadel		return;
151507cadf262fe67cd71e02247b240706be12f1042David Spinadel
152507cadf262fe67cd71e02247b240706be12f1042David Spinadel	phy_id = mvmvif->phy_ctxt->id;
153507cadf262fe67cd71e02247b240706be12f1042David Spinadel	beacon_int = mvm->noa_vif->bss_conf.beacon_int;
154507cadf262fe67cd71e02247b240706be12f1042David Spinadel
155507cadf262fe67cd71e02247b240706be12f1042David Spinadel	for (i = 0; i < MAX_BINDINGS; i++) {
156507cadf262fe67cd71e02247b240706be12f1042David Spinadel		u32 id_n_c = le32_to_cpu(cmd->quotas[i].id_and_color);
157507cadf262fe67cd71e02247b240706be12f1042David Spinadel		u32 id = (id_n_c & FW_CTXT_ID_MSK) >> FW_CTXT_ID_POS;
158507cadf262fe67cd71e02247b240706be12f1042David Spinadel		u32 quota = le32_to_cpu(cmd->quotas[i].quota);
159507cadf262fe67cd71e02247b240706be12f1042David Spinadel
160507cadf262fe67cd71e02247b240706be12f1042David Spinadel		if (id != phy_id)
161507cadf262fe67cd71e02247b240706be12f1042David Spinadel			continue;
162507cadf262fe67cd71e02247b240706be12f1042David Spinadel
163246dd9922e859768aa522daa6c1c601785e57e0cDavid Spinadel		quota *= (beacon_int - mvm->noa_duration);
164246dd9922e859768aa522daa6c1c601785e57e0cDavid Spinadel		quota /= beacon_int;
165507cadf262fe67cd71e02247b240706be12f1042David Spinadel
166a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg		IWL_DEBUG_QUOTA(mvm, "quota: adjust for NoA from %d to %d\n",
167a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg				le32_to_cpu(cmd->quotas[i].quota), quota);
168a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg
169507cadf262fe67cd71e02247b240706be12f1042David Spinadel		cmd->quotas[i].quota = cpu_to_le32(quota);
170507cadf262fe67cd71e02247b240706be12f1042David Spinadel	}
171507cadf262fe67cd71e02247b240706be12f1042David Spinadel#endif
172507cadf262fe67cd71e02247b240706be12f1042David Spinadel}
173507cadf262fe67cd71e02247b240706be12f1042David Spinadel
1740166230c6c696d501a2d2616a30e295b71e39d43Johannes Bergint iwl_mvm_update_quotas(struct iwl_mvm *mvm,
1750166230c6c696d501a2d2616a30e295b71e39d43Johannes Berg			  struct ieee80211_vif *disabled_vif)
1768ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg{
177f5e45f2d960cea226b9d173e232c94c4c388c1bcJohannes Berg	struct iwl_time_quota_cmd cmd = {};
178b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg	int i, idx, err, num_active_macs, quota, quota_rem, n_non_lowlat;
1798ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	struct iwl_mvm_quota_iterator_data data = {
1808ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		.n_interfaces = {},
1818ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		.colors = { -1, -1, -1, -1 },
1820166230c6c696d501a2d2616a30e295b71e39d43Johannes Berg		.disabled_vif = disabled_vif,
1838ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	};
184b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg	struct iwl_time_quota_cmd *last = &mvm->last_quota_cmd;
185b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg	bool send = false;
1868ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
187f5e45f2d960cea226b9d173e232c94c4c388c1bcJohannes Berg	lockdep_assert_held(&mvm->mutex);
188f5e45f2d960cea226b9d173e232c94c4c388c1bcJohannes Berg
1898ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	/* update all upon completion */
1908ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
1918ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		return 0;
1928ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
193f5e45f2d960cea226b9d173e232c94c4c388c1bcJohannes Berg	/* iterator data above must match */
194f5e45f2d960cea226b9d173e232c94c4c388c1bcJohannes Berg	BUILD_BUG_ON(MAX_BINDINGS != 4);
1958ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
1968ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	ieee80211_iterate_active_interfaces_atomic(
1978ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1988ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		iwl_mvm_quota_iterator, &data);
1998ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
20035adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer	/*
20135adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer	 * The FW's scheduling session consists of
20235adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer	 * IWL_MVM_MAX_QUOTA fragments. Divide these fragments
20335adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer	 * equally between all the bindings that require quota
20435adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer	 */
2057b8359cf2bda0103688f9cc623ce6c221a6004c1Johannes Berg	num_active_macs = 0;
20635adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer	for (i = 0; i < MAX_BINDINGS; i++) {
20735adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer		cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
2087b8359cf2bda0103688f9cc623ce6c221a6004c1Johannes Berg		num_active_macs += data.n_interfaces[i];
20935adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer	}
21035adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer
2116ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg	n_non_lowlat = num_active_macs;
2126ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg
2136ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg	if (data.n_low_latency_bindings == 1) {
2146ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		for (i = 0; i < MAX_BINDINGS; i++) {
2156ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg			if (data.low_latency[i]) {
2166ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg				n_non_lowlat -= data.n_interfaces[i];
2176ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg				break;
2186ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg			}
2196ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		}
2207b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer	}
2217b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer
2227b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer	if (data.n_low_latency_bindings == 1 && n_non_lowlat) {
2237b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		/*
2247b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		 * Reserve quota for the low latency binding in case that
2257b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		 * there are several data bindings but only a single
2267b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		 * low latency one. Split the rest of the quota equally
2277b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		 * between the other data interfaces.
2287b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		 */
2297b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		quota = (QUOTA_100 - QUOTA_LOWLAT_MIN) / n_non_lowlat;
2307b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		quota_rem = QUOTA_100 - n_non_lowlat * quota -
2317b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer			    QUOTA_LOWLAT_MIN;
232a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg		IWL_DEBUG_QUOTA(mvm,
233a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg				"quota: low-latency binding active, remaining quota per other binding: %d\n",
234a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg				quota);
2356ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg	} else if (num_active_macs) {
2367b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		/*
2377b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		 * There are 0 or more than 1 low latency bindings, or all the
2387b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		 * data interfaces belong to the single low latency binding.
2397b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		 * Split the quota equally between the data interfaces.
2407b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		 */
2416ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		quota = QUOTA_100 / num_active_macs;
2426ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		quota_rem = QUOTA_100 % num_active_macs;
243a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg		IWL_DEBUG_QUOTA(mvm,
244a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg				"quota: splitting evenly per binding: %d\n",
245a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg				quota);
2466ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg	} else {
2476ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		/* values don't really matter - won't be used */
2486ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		quota = 0;
2496ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg		quota_rem = 0;
2508d683b79487c40d2a74ab9c484bde1929e016579Ilan Peer	}
25135adfd6e458741d3d3fca1ce0e342919eb250c2bIlan Peer
2528ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	for (idx = 0, i = 0; i < MAX_BINDINGS; i++) {
2538d683b79487c40d2a74ab9c484bde1929e016579Ilan Peer		if (data.colors[i] < 0)
2548ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg			continue;
2558ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
2568ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		cmd.quotas[idx].id_and_color =
2578ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg			cpu_to_le32(FW_CMD_ID_AND_COLOR(i, data.colors[i]));
2588d683b79487c40d2a74ab9c484bde1929e016579Ilan Peer
2591fb184b4a43d2ef303361efa5a166a60e4b4374aJohannes Berg		if (data.n_interfaces[i] <= 0)
2608d683b79487c40d2a74ab9c484bde1929e016579Ilan Peer			cmd.quotas[idx].quota = cpu_to_le32(0);
2611fb184b4a43d2ef303361efa5a166a60e4b4374aJohannes Berg		else if (data.n_low_latency_bindings == 1 && n_non_lowlat &&
2621fb184b4a43d2ef303361efa5a166a60e4b4374aJohannes Berg			 data.low_latency[i])
2637b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer			/*
2647b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer			 * There is more than one binding, but only one of the
2657b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer			 * bindings is in low latency. For this case, allocate
2667b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer			 * the minimal required quota for the low latency
2677b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer			 * binding.
2687b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer			 */
2696ca40d6eae3e36068157412ceb9ddf1f2d53d1c8Johannes Berg			cmd.quotas[idx].quota = cpu_to_le32(QUOTA_LOWLAT_MIN);
2701fb184b4a43d2ef303361efa5a166a60e4b4374aJohannes Berg		else
2717b8359cf2bda0103688f9cc623ce6c221a6004c1Johannes Berg			cmd.quotas[idx].quota =
2727b8359cf2bda0103688f9cc623ce6c221a6004c1Johannes Berg				cpu_to_le32(quota * data.n_interfaces[i]);
2731fb184b4a43d2ef303361efa5a166a60e4b4374aJohannes Berg
2747b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer		WARN_ONCE(le32_to_cpu(cmd.quotas[idx].quota) > QUOTA_100,
2757b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer			  "Binding=%d, quota=%u > max=%u\n",
2767b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer			  idx, le32_to_cpu(cmd.quotas[idx].quota), QUOTA_100);
2777b4fe06c25a1a37ba393e791012f3b01c70e674aIlan Peer
27865d66628500a40e2acbf1546af536801d65e0d14Johannes Berg		cmd.quotas[idx].max_duration = cpu_to_le32(0);
2791fb184b4a43d2ef303361efa5a166a60e4b4374aJohannes Berg
2808ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg		idx++;
2818ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg	}
2828ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
2832d675e523740d20fea8b8b76b4163aa18811c288Ilan Peer	/* Give the remainder of the session to the first data binding */
2842d675e523740d20fea8b8b76b4163aa18811c288Ilan Peer	for (i = 0; i < MAX_BINDINGS; i++) {
2852d675e523740d20fea8b8b76b4163aa18811c288Ilan Peer		if (le32_to_cpu(cmd.quotas[i].quota) != 0) {
2862d675e523740d20fea8b8b76b4163aa18811c288Ilan Peer			le32_add_cpu(&cmd.quotas[i].quota, quota_rem);
287a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg			IWL_DEBUG_QUOTA(mvm,
288a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg					"quota: giving remainder of %d to binding %d\n",
289a43ad46a450b1a4466f34b057522f56c125710fbJohannes Berg					quota_rem, i);
2902d675e523740d20fea8b8b76b4163aa18811c288Ilan Peer			break;
2912d675e523740d20fea8b8b76b4163aa18811c288Ilan Peer		}
2922d675e523740d20fea8b8b76b4163aa18811c288Ilan Peer	}
2938ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg
294507cadf262fe67cd71e02247b240706be12f1042David Spinadel	iwl_mvm_adjust_quota_for_noa(mvm, &cmd);
295507cadf262fe67cd71e02247b240706be12f1042David Spinadel
29699a1230d9d1cb5d52bb37b8c03f3931502f0e44dJohannes Berg	/* check that we have non-zero quota for all valid bindings */
29799a1230d9d1cb5d52bb37b8c03f3931502f0e44dJohannes Berg	for (i = 0; i < MAX_BINDINGS; i++) {
298b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg		if (cmd.quotas[i].id_and_color != last->quotas[i].id_and_color)
299b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg			send = true;
300b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg		if (cmd.quotas[i].max_duration != last->quotas[i].max_duration)
301b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg			send = true;
302b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg		if (abs((int)le32_to_cpu(cmd.quotas[i].quota) -
303b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg			(int)le32_to_cpu(last->quotas[i].quota))
304b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg						> IWL_MVM_QUOTA_THRESHOLD)
305b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg			send = true;
30699a1230d9d1cb5d52bb37b8c03f3931502f0e44dJohannes Berg		if (cmd.quotas[i].id_and_color == cpu_to_le32(FW_CTXT_INVALID))
30799a1230d9d1cb5d52bb37b8c03f3931502f0e44dJohannes Berg			continue;
30899a1230d9d1cb5d52bb37b8c03f3931502f0e44dJohannes Berg		WARN_ONCE(cmd.quotas[i].quota == 0,
30999a1230d9d1cb5d52bb37b8c03f3931502f0e44dJohannes Berg			  "zero quota on binding %d\n", i);
31099a1230d9d1cb5d52bb37b8c03f3931502f0e44dJohannes Berg	}
31199a1230d9d1cb5d52bb37b8c03f3931502f0e44dJohannes Berg
3123d4060d58130aa805fb505c8ed4a9fbf8a3e09beJohannes Berg	if (!send) {
313b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg		/* don't send a practically unchanged command, the firmware has
314b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg		 * to re-initialize a lot of state and that can have an adverse
315b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg		 * impact on it
316b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg		 */
3173d4060d58130aa805fb505c8ed4a9fbf8a3e09beJohannes Berg		return 0;
318b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg	}
319b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg
3203d4060d58130aa805fb505c8ed4a9fbf8a3e09beJohannes Berg	err = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0, sizeof(cmd), &cmd);
3213d4060d58130aa805fb505c8ed4a9fbf8a3e09beJohannes Berg
322b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg	if (err)
323b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg		IWL_ERR(mvm, "Failed to send quota: %d\n", err);
324b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg	else
325b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg		mvm->last_quota_cmd = cmd;
326b2b7875bfb6c69bb708b61c5f745491d240161a1Johannes Berg	return err;
3278ca151b568b67a7b72dcfc6ee6ea7c107ddd795cJohannes Berg}
328