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