aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGregory Greenman <gregory.greenman@intel.com>2017-11-05 11:49:48 -0500
committerLuca Coelho <luciano.coelho@intel.com>2017-12-05 14:01:41 -0500
commit9f66a397c8773167939c4eafc33725f38ec5c872 (patch)
treed088dc60a2d3864409bf8471aafc73c6c20473f5
parentecaf71de414345c68a05c403d33dd0cd89b2c85f (diff)
iwlwifi: mvm: rs: add ops for the new rate scaling in the FW
This patch introduces a new instance of rate_control_ops for the new API (adding only empty stubs here and the subsequent patches in the series will fill in the implementation). The decision which API to use is done during the register step according to FW TLV. Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/Makefile2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c85
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c89
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c8
8 files changed, 166 insertions, 48 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile
index a47635c32c11..9ffd21918b5a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile
@@ -2,7 +2,7 @@
2obj-$(CONFIG_IWLMVM) += iwlmvm.o 2obj-$(CONFIG_IWLMVM) += iwlmvm.o
3iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o 3iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
4iwlmvm-y += utils.o rx.o rxmq.o tx.o binding.o quota.o sta.o sf.o 4iwlmvm-y += utils.o rx.o rxmq.o tx.o binding.o quota.o sta.o sf.o
5iwlmvm-y += scan.o time-event.o rs.o 5iwlmvm-y += scan.o time-event.o rs.o rs-fw.o
6iwlmvm-y += power.o coex.o 6iwlmvm-y += power.o coex.o
7iwlmvm-y += tt.o offloading.o tdls.o 7iwlmvm-y += tt.o offloading.o tdls.o
8iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o 8iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 4ff099f462fb..e7abca2441a3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -460,7 +460,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
460 /* this is the case for CCK frames, it's better (only 8) for OFDM */ 460 /* this is the case for CCK frames, it's better (only 8) for OFDM */
461 hw->radiotap_timestamp.accuracy = 22; 461 hw->radiotap_timestamp.accuracy = 22;
462 462
463 hw->rate_control_algorithm = "iwl-mvm-rs"; 463 if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD))
464 hw->rate_control_algorithm = RS_NAME;
465
464 hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES; 466 hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
465 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; 467 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
466 468
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 7078b7e458be..a38a55327bcb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -127,11 +127,8 @@ static int __init iwl_mvm_init(void)
127 } 127 }
128 128
129 ret = iwl_opmode_register("iwlmvm", &iwl_mvm_ops); 129 ret = iwl_opmode_register("iwlmvm", &iwl_mvm_ops);
130 130 if (ret)
131 if (ret) {
132 pr_err("Unable to register MVM op_mode: %d\n", ret); 131 pr_err("Unable to register MVM op_mode: %d\n", ret);
133 iwl_mvm_rate_control_unregister();
134 }
135 132
136 return ret; 133 return ret;
137} 134}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
new file mode 100644
index 000000000000..aae55b26a397
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -0,0 +1,85 @@
1/******************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright(c) 2017 Intel Deutschland GmbH
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * The full GNU General Public License is included in this distribution
20 * in the file called COPYING.
21 *
22 * Contact Information:
23 * Intel Linux Wireless <linuxwifi@intel.com>
24 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
25 *
26 * BSD LICENSE
27 *
28 * Copyright(c) 2017 Intel Deutschland GmbH
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 *
35 * * Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * * Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in
39 * the documentation and/or other materials provided with the
40 * distribution.
41 * * Neither the name Intel Corporation nor the names of its
42 * contributors may be used to endorse or promote products derived
43 * from this software without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
47 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
48 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
49 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
55 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 *
57 *****************************************************************************/
58#include "rs.h"
59#include "fw-api.h"
60#include "sta.h"
61#include "iwl-op-mode.h"
62#include "mvm.h"
63
64void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
65 enum nl80211_band band)
66{
67}
68
69void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
70{
71 struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
72
73 IWL_DEBUG_RATE(mvm, "create station rate scale window\n");
74
75 lq_sta->pers.drv = mvm;
76 lq_sta->pers.sta_id = mvmsta->sta_id;
77 lq_sta->pers.chains = 0;
78 memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal));
79 lq_sta->pers.last_rssi = S8_MIN;
80 lq_sta->last_rate_n_flags = 0;
81
82#ifdef CPTCFG_MAC80211_DEBUGFS
83 lq_sta->pers.dbg_fixed_rate = 0;
84#endif
85}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index 739c47dbc6e8..3dd6535ed922 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -42,8 +42,6 @@
42#include "mvm.h" 42#include "mvm.h"
43#include "debugfs.h" 43#include "debugfs.h"
44 44
45#define RS_NAME "iwl-mvm-rs"
46
47#define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ 45#define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */
48 46
49/* Calculations of success ratio are done in fixed point where 12800 is 100%. 47/* Calculations of success ratio are done in fixed point where 12800 is 100%.
@@ -1416,13 +1414,13 @@ done:
1416/* 1414/*
1417 * mac80211 sends us Tx status 1415 * mac80211 sends us Tx status
1418 */ 1416 */
1419static void rs_mac80211_tx_status(void *mvm_r, 1417static void rs_drv_mac80211_tx_status(void *mvm_r,
1420 struct ieee80211_supported_band *sband, 1418 struct ieee80211_supported_band *sband,
1421 struct ieee80211_sta *sta, void *priv_sta, 1419 struct ieee80211_sta *sta, void *priv_sta,
1422 struct sk_buff *skb) 1420 struct sk_buff *skb)
1423{ 1421{
1424 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 1422 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1425 struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_r; 1423 struct iwl_op_mode *op_mode = mvm_r;
1426 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 1424 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
1427 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1425 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1428 1426
@@ -2857,8 +2855,9 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
2857 iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init); 2855 iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init);
2858} 2856}
2859 2857
2860static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta, 2858static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
2861 struct ieee80211_tx_rate_control *txrc) 2859 void *mvm_sta,
2860 struct ieee80211_tx_rate_control *txrc)
2862{ 2861{
2863 struct iwl_op_mode *op_mode = mvm_r; 2862 struct iwl_op_mode *op_mode = mvm_r;
2864 struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode); 2863 struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode);
@@ -2900,8 +2899,8 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
2900 } 2899 }
2901} 2900}
2902 2901
2903static void *rs_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta, 2902static void *rs_drv_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
2904 gfp_t gfp) 2903 gfp_t gfp)
2905{ 2904{
2906 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 2905 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
2907 struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_rate; 2906 struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_rate;
@@ -3037,7 +3036,7 @@ static void rs_vht_init(struct iwl_mvm *mvm,
3037} 3036}
3038 3037
3039#ifdef CONFIG_IWLWIFI_DEBUGFS 3038#ifdef CONFIG_IWLWIFI_DEBUGFS
3040static void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm) 3039void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm)
3041{ 3040{
3042 spin_lock_bh(&mvm->drv_stats_lock); 3041 spin_lock_bh(&mvm->drv_stats_lock);
3043 memset(&mvm->drv_rx_stats, 0, sizeof(mvm->drv_rx_stats)); 3042 memset(&mvm->drv_rx_stats, 0, sizeof(mvm->drv_rx_stats));
@@ -3105,8 +3104,8 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
3105/* 3104/*
3106 * Called after adding a new station to initialize rate scaling 3105 * Called after adding a new station to initialize rate scaling
3107 */ 3106 */
3108void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, 3107static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
3109 enum nl80211_band band, bool init) 3108 enum nl80211_band band, bool init)
3110{ 3109{
3111 int i, j; 3110 int i, j;
3112 struct ieee80211_hw *hw = mvm->hw; 3111 struct ieee80211_hw *hw = mvm->hw;
@@ -3188,16 +3187,15 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
3188 rs_initialize_lq(mvm, sta, lq_sta, band, init); 3187 rs_initialize_lq(mvm, sta, lq_sta, band, init);
3189} 3188}
3190 3189
3191static void rs_rate_update(void *mvm_r, 3190static void rs_drv_rate_update(void *mvm_r,
3192 struct ieee80211_supported_band *sband, 3191 struct ieee80211_supported_band *sband,
3193 struct cfg80211_chan_def *chandef, 3192 struct cfg80211_chan_def *chandef,
3194 struct ieee80211_sta *sta, void *priv_sta, 3193 struct ieee80211_sta *sta,
3195 u32 changed) 3194 void *priv_sta, u32 changed)
3196{ 3195{
3196 struct iwl_op_mode *op_mode = mvm_r;
3197 struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode);
3197 u8 tid; 3198 u8 tid;
3198 struct iwl_op_mode *op_mode =
3199 (struct iwl_op_mode *)mvm_r;
3200 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
3201 3199
3202 if (!iwl_mvm_sta_from_mac80211(sta)->vif) 3200 if (!iwl_mvm_sta_from_mac80211(sta)->vif)
3203 return; 3201 return;
@@ -3564,14 +3562,14 @@ static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
3564{ 3562{
3565 return hw->priv; 3563 return hw->priv;
3566} 3564}
3565
3567/* rate scale requires free function to be implemented */ 3566/* rate scale requires free function to be implemented */
3568static void rs_free(void *mvm_rate) 3567static void rs_free(void *mvm_rate)
3569{ 3568{
3570 return; 3569 return;
3571} 3570}
3572 3571
3573static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, 3572static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta)
3574 void *mvm_sta)
3575{ 3573{
3576 struct iwl_op_mode *op_mode __maybe_unused = mvm_r; 3574 struct iwl_op_mode *op_mode __maybe_unused = mvm_r;
3577 struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode); 3575 struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode);
@@ -3982,7 +3980,8 @@ static ssize_t iwl_dbgfs_ss_force_write(struct iwl_lq_sta *lq_sta, char *buf,
3982 3980
3983MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32); 3981MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32);
3984 3982
3985static void rs_add_debugfs(void *mvm, void *priv_sta, struct dentry *dir) 3983static void rs_drv_add_sta_debugfs(void *mvm, void *priv_sta,
3984 struct dentry *dir)
3986{ 3985{
3987 struct iwl_lq_sta *lq_sta = priv_sta; 3986 struct iwl_lq_sta *lq_sta = priv_sta;
3988 struct iwl_mvm_sta *mvmsta; 3987 struct iwl_mvm_sta *mvmsta;
@@ -4009,7 +4008,7 @@ err:
4009 IWL_ERR((struct iwl_mvm *)mvm, "Can't create debugfs entity\n"); 4008 IWL_ERR((struct iwl_mvm *)mvm, "Can't create debugfs entity\n");
4010} 4009}
4011 4010
4012static void rs_remove_debugfs(void *mvm, void *mvm_sta) 4011void rs_remove_sta_debugfs(void *mvm, void *mvm_sta)
4013{ 4012{
4014} 4013}
4015#endif 4014#endif
@@ -4019,37 +4018,47 @@ static void rs_remove_debugfs(void *mvm, void *mvm_sta)
4019 * the station is added. Since mac80211 calls this function before a 4018 * the station is added. Since mac80211 calls this function before a
4020 * station is added we ignore it. 4019 * station is added we ignore it.
4021 */ 4020 */
4022static void rs_rate_init_stub(void *mvm_r, 4021static void rs_rate_init_ops(void *mvm_r,
4023 struct ieee80211_supported_band *sband, 4022 struct ieee80211_supported_band *sband,
4024 struct cfg80211_chan_def *chandef, 4023 struct cfg80211_chan_def *chandef,
4025 struct ieee80211_sta *sta, void *mvm_sta) 4024 struct ieee80211_sta *sta, void *mvm_sta)
4026{ 4025{
4027} 4026}
4028 4027
4029static const struct rate_control_ops rs_mvm_ops = { 4028/* ops for rate scaling implemented in the driver */
4029static const struct rate_control_ops rs_mvm_ops_drv = {
4030 .name = RS_NAME, 4030 .name = RS_NAME,
4031 .tx_status = rs_mac80211_tx_status, 4031 .tx_status = rs_drv_mac80211_tx_status,
4032 .get_rate = rs_get_rate, 4032 .get_rate = rs_drv_get_rate,
4033 .rate_init = rs_rate_init_stub, 4033 .rate_init = rs_rate_init_ops,
4034 .alloc = rs_alloc, 4034 .alloc = rs_alloc,
4035 .free = rs_free, 4035 .free = rs_free,
4036 .alloc_sta = rs_alloc_sta, 4036 .alloc_sta = rs_drv_alloc_sta,
4037 .free_sta = rs_free_sta, 4037 .free_sta = rs_free_sta,
4038 .rate_update = rs_rate_update, 4038 .rate_update = rs_drv_rate_update,
4039#ifdef CONFIG_MAC80211_DEBUGFS 4039#ifdef CONFIG_MAC80211_DEBUGFS
4040 .add_sta_debugfs = rs_add_debugfs, 4040 .add_sta_debugfs = rs_drv_add_sta_debugfs,
4041 .remove_sta_debugfs = rs_remove_debugfs, 4041 .remove_sta_debugfs = rs_remove_sta_debugfs,
4042#endif 4042#endif
4043}; 4043};
4044 4044
4045void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
4046 enum nl80211_band band, bool init)
4047{
4048 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD))
4049 rs_fw_rate_init(mvm, sta, band);
4050 else
4051 rs_drv_rate_init(mvm, sta, band, init);
4052}
4053
4045int iwl_mvm_rate_control_register(void) 4054int iwl_mvm_rate_control_register(void)
4046{ 4055{
4047 return ieee80211_rate_control_register(&rs_mvm_ops); 4056 return ieee80211_rate_control_register(&rs_mvm_ops_drv);
4048} 4057}
4049 4058
4050void iwl_mvm_rate_control_unregister(void) 4059void iwl_mvm_rate_control_unregister(void)
4051{ 4060{
4052 ieee80211_rate_control_unregister(&rs_mvm_ops); 4061 ieee80211_rate_control_unregister(&rs_mvm_ops_drv);
4053} 4062}
4054 4063
4055/** 4064/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
index 5075a8061c82..eb92ded8a4dc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
@@ -36,6 +36,8 @@
36#include "fw-api.h" 36#include "fw-api.h"
37#include "iwl-trans.h" 37#include "iwl-trans.h"
38 38
39#define RS_NAME "iwl-mvm-rs"
40
39struct iwl_rs_rate_info { 41struct iwl_rs_rate_info {
40 u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ 42 u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
41 u8 plcp_ht_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ 43 u8 plcp_ht_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
@@ -438,4 +440,16 @@ struct iwl_mvm_sta;
438 440
439int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, 441int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
440 bool enable); 442 bool enable);
443
444#ifdef CONFIG_IWLWIFI_DEBUGFS
445void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm);
446#endif
447
448#ifdef CONFIG_MAC80211_DEBUGFS
449void rs_remove_sta_debugfs(void *mvm, void *mvm_sta);
450#endif
451
452void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta);
453void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
454 enum nl80211_band band);
441#endif /* __rs__ */ 455#endif /* __rs__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 12875f773a86..6ed9a8eae107 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1439,6 +1439,13 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
1439 goto err; 1439 goto err;
1440 } 1440 }
1441 1441
1442 /*
1443 * if rs is registered with mac80211, then "add station" will be handled
1444 * via the corresponding ops, otherwise need to notify rate scaling here
1445 */
1446 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TLC_OFFLOAD))
1447 iwl_mvm_rs_add_sta(mvm, mvm_sta);
1448
1442update_fw: 1449update_fw:
1443 ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags); 1450 ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags);
1444 if (ret) 1451 if (ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 9e7beecf043a..b65b4e8f8606 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1718,8 +1718,12 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
1718 ba_info->band = chanctx_conf->def.chan->band; 1718 ba_info->band = chanctx_conf->def.chan->band;
1719 iwl_mvm_hwrate_to_tx_status(rate, ba_info); 1719 iwl_mvm_hwrate_to_tx_status(rate, ba_info);
1720 1720
1721 IWL_DEBUG_TX_REPLY(mvm, "No reclaim. Update rs directly\n"); 1721 if (!fw_has_capa(&mvm->fw->ucode_capa,
1722 iwl_mvm_rs_tx_status(mvm, sta, tid, ba_info, false); 1722 IWL_UCODE_TLV_CAPA_TLC_OFFLOAD)) {
1723 IWL_DEBUG_TX_REPLY(mvm,
1724 "No reclaim. Update rs directly\n");
1725 iwl_mvm_rs_tx_status(mvm, sta, tid, ba_info, false);
1726 }
1723 } 1727 }
1724 1728
1725out: 1729out: