1 /******************************************************************************
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.
8 * Copyright(c) 2017 Intel Deutschland GmbH
9 * Copyright(c) 2018 - 2020 Intel Corporation
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * The full GNU General Public License is included in this distribution
21 * in the file called COPYING.
23 * Contact Information:
24 * Intel Linux Wireless <linuxwifi@intel.com>
25 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
29 * Copyright(c) 2017 Intel Deutschland GmbH
30 * Copyright(c) 2018 - 2020 Intel Corporation
31 * All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
37 * * Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * * Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in
41 * the documentation and/or other materials provided with the
43 * * Neither the name Intel Corporation nor the names of its
44 * contributors may be used to endorse or promote products derived
45 * from this software without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
50 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
51 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
57 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 *****************************************************************************/
63 #include "iwl-op-mode.h"
66 static u8
rs_fw_bw_from_sta_bw(struct ieee80211_sta
*sta
)
68 switch (sta
->bandwidth
) {
69 case IEEE80211_STA_RX_BW_160
:
70 return IWL_TLC_MNG_CH_WIDTH_160MHZ
;
71 case IEEE80211_STA_RX_BW_80
:
72 return IWL_TLC_MNG_CH_WIDTH_80MHZ
;
73 case IEEE80211_STA_RX_BW_40
:
74 return IWL_TLC_MNG_CH_WIDTH_40MHZ
;
75 case IEEE80211_STA_RX_BW_20
:
77 return IWL_TLC_MNG_CH_WIDTH_20MHZ
;
81 static u8
rs_fw_set_active_chains(u8 chains
)
86 fw_chains
|= IWL_TLC_MNG_CHAIN_A_MSK
;
88 fw_chains
|= IWL_TLC_MNG_CHAIN_B_MSK
;
91 "tlc offload doesn't support antenna C. chains: 0x%x\n",
97 static u8
rs_fw_sgi_cw_support(struct ieee80211_sta
*sta
)
99 struct ieee80211_sta_ht_cap
*ht_cap
= &sta
->ht_cap
;
100 struct ieee80211_sta_vht_cap
*vht_cap
= &sta
->vht_cap
;
101 struct ieee80211_sta_he_cap
*he_cap
= &sta
->he_cap
;
107 if (ht_cap
->cap
& IEEE80211_HT_CAP_SGI_20
)
108 supp
|= BIT(IWL_TLC_MNG_CH_WIDTH_20MHZ
);
109 if (ht_cap
->cap
& IEEE80211_HT_CAP_SGI_40
)
110 supp
|= BIT(IWL_TLC_MNG_CH_WIDTH_40MHZ
);
111 if (vht_cap
->cap
& IEEE80211_VHT_CAP_SHORT_GI_80
)
112 supp
|= BIT(IWL_TLC_MNG_CH_WIDTH_80MHZ
);
113 if (vht_cap
->cap
& IEEE80211_VHT_CAP_SHORT_GI_160
)
114 supp
|= BIT(IWL_TLC_MNG_CH_WIDTH_160MHZ
);
119 static u16
rs_fw_get_config_flags(struct iwl_mvm
*mvm
,
120 struct ieee80211_sta
*sta
,
121 struct ieee80211_supported_band
*sband
)
123 struct ieee80211_sta_ht_cap
*ht_cap
= &sta
->ht_cap
;
124 struct ieee80211_sta_vht_cap
*vht_cap
= &sta
->vht_cap
;
125 struct ieee80211_sta_he_cap
*he_cap
= &sta
->he_cap
;
126 bool vht_ena
= vht_cap
->vht_supported
;
129 if (mvm
->cfg
->ht_params
->stbc
&&
130 (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm
)) > 1)) {
131 if (he_cap
->has_he
) {
132 if (he_cap
->he_cap_elem
.phy_cap_info
[2] &
133 IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ
)
134 flags
|= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK
;
136 if (he_cap
->he_cap_elem
.phy_cap_info
[7] &
137 IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ
)
138 flags
|= IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK
;
139 } else if ((ht_cap
->cap
& IEEE80211_HT_CAP_RX_STBC
) ||
141 (vht_cap
->cap
& IEEE80211_VHT_CAP_RXSTBC_MASK
)))
142 flags
|= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK
;
145 if (mvm
->cfg
->ht_params
->ldpc
&&
146 ((ht_cap
->cap
& IEEE80211_HT_CAP_LDPC_CODING
) ||
147 (vht_ena
&& (vht_cap
->cap
& IEEE80211_VHT_CAP_RXLDPC
))))
148 flags
|= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK
;
150 /* consider LDPC support in case of HE */
151 if (he_cap
->has_he
&& (he_cap
->he_cap_elem
.phy_cap_info
[1] &
152 IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD
))
153 flags
|= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK
;
155 if (sband
->iftype_data
&& sband
->iftype_data
->he_cap
.has_he
&&
156 !(sband
->iftype_data
->he_cap
.he_cap_elem
.phy_cap_info
[1] &
157 IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD
))
158 flags
&= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK
;
160 if (he_cap
->has_he
&&
161 (he_cap
->he_cap_elem
.phy_cap_info
[3] &
162 IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK
))
163 flags
|= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK
;
169 int rs_fw_vht_highest_rx_mcs_index(const struct ieee80211_sta_vht_cap
*vht_cap
,
172 u16 rx_mcs
= le16_to_cpu(vht_cap
->vht_mcs
.rx_mcs_map
) &
173 (0x3 << (2 * (nss
- 1)));
174 rx_mcs
>>= (2 * (nss
- 1));
177 case IEEE80211_VHT_MCS_SUPPORT_0_7
:
178 return IWL_TLC_MNG_HT_RATE_MCS7
;
179 case IEEE80211_VHT_MCS_SUPPORT_0_8
:
180 return IWL_TLC_MNG_HT_RATE_MCS8
;
181 case IEEE80211_VHT_MCS_SUPPORT_0_9
:
182 return IWL_TLC_MNG_HT_RATE_MCS9
;
192 rs_fw_vht_set_enabled_rates(const struct ieee80211_sta
*sta
,
193 const struct ieee80211_sta_vht_cap
*vht_cap
,
194 struct iwl_tlc_config_cmd
*cmd
)
198 u8 nss
= sta
->rx_nss
;
200 /* the station support only a single receive chain */
201 if (sta
->smps_mode
== IEEE80211_SMPS_STATIC
)
204 for (i
= 0; i
< nss
&& i
< IWL_TLC_NSS_MAX
; i
++) {
205 highest_mcs
= rs_fw_vht_highest_rx_mcs_index(vht_cap
, i
+ 1);
209 supp
= BIT(highest_mcs
+ 1) - 1;
210 if (sta
->bandwidth
== IEEE80211_STA_RX_BW_20
)
211 supp
&= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9
);
213 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_NONE_160
] = cpu_to_le16(supp
);
214 if (sta
->bandwidth
== IEEE80211_STA_RX_BW_160
)
215 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_160
] =
216 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_NONE_160
];
220 static u16
rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs
)
223 case IEEE80211_HE_MCS_SUPPORT_0_7
:
224 return BIT(IWL_TLC_MNG_HT_RATE_MCS7
+ 1) - 1;
225 case IEEE80211_HE_MCS_SUPPORT_0_9
:
226 return BIT(IWL_TLC_MNG_HT_RATE_MCS9
+ 1) - 1;
227 case IEEE80211_HE_MCS_SUPPORT_0_11
:
228 return BIT(IWL_TLC_MNG_HT_RATE_MCS11
+ 1) - 1;
229 case IEEE80211_HE_MCS_NOT_SUPPORTED
:
233 WARN(1, "invalid HE MCS %d\n", mcs
);
238 rs_fw_he_set_enabled_rates(const struct ieee80211_sta
*sta
,
239 struct ieee80211_supported_band
*sband
,
240 struct iwl_tlc_config_cmd
*cmd
)
242 const struct ieee80211_sta_he_cap
*he_cap
= &sta
->he_cap
;
243 u16 mcs_160
= le16_to_cpu(he_cap
->he_mcs_nss_supp
.rx_mcs_160
);
244 u16 mcs_80
= le16_to_cpu(he_cap
->he_mcs_nss_supp
.rx_mcs_80
);
246 le16_to_cpu(sband
->iftype_data
->he_cap
.he_mcs_nss_supp
.tx_mcs_80
);
248 le16_to_cpu(sband
->iftype_data
->he_cap
.he_mcs_nss_supp
.tx_mcs_160
);
250 u8 nss
= sta
->rx_nss
;
252 /* the station support only a single receive chain */
253 if (sta
->smps_mode
== IEEE80211_SMPS_STATIC
)
256 for (i
= 0; i
< nss
&& i
< IWL_TLC_NSS_MAX
; i
++) {
257 u16 _mcs_160
= (mcs_160
>> (2 * i
)) & 0x3;
258 u16 _mcs_80
= (mcs_80
>> (2 * i
)) & 0x3;
259 u16 _tx_mcs_160
= (tx_mcs_160
>> (2 * i
)) & 0x3;
260 u16 _tx_mcs_80
= (tx_mcs_80
>> (2 * i
)) & 0x3;
262 /* If one side doesn't support - mark both as not supporting */
263 if (_mcs_80
== IEEE80211_HE_MCS_NOT_SUPPORTED
||
264 _tx_mcs_80
== IEEE80211_HE_MCS_NOT_SUPPORTED
) {
265 _mcs_80
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
266 _tx_mcs_80
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
268 if (_mcs_80
> _tx_mcs_80
)
269 _mcs_80
= _tx_mcs_80
;
270 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_NONE_160
] =
271 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80
));
273 /* If one side doesn't support - mark both as not supporting */
274 if (_mcs_160
== IEEE80211_HE_MCS_NOT_SUPPORTED
||
275 _tx_mcs_160
== IEEE80211_HE_MCS_NOT_SUPPORTED
) {
276 _mcs_160
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
277 _tx_mcs_160
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
279 if (_mcs_160
> _tx_mcs_160
)
280 _mcs_160
= _tx_mcs_160
;
281 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_160
] =
282 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160
));
286 static void rs_fw_set_supp_rates(struct ieee80211_sta
*sta
,
287 struct ieee80211_supported_band
*sband
,
288 struct iwl_tlc_config_cmd
*cmd
)
292 unsigned long supp
; /* must be unsigned long for for_each_set_bit */
293 const struct ieee80211_sta_ht_cap
*ht_cap
= &sta
->ht_cap
;
294 const struct ieee80211_sta_vht_cap
*vht_cap
= &sta
->vht_cap
;
295 const struct ieee80211_sta_he_cap
*he_cap
= &sta
->he_cap
;
299 tmp
= sta
->supp_rates
[sband
->band
];
300 for_each_set_bit(i
, &tmp
, BITS_PER_LONG
)
301 supp
|= BIT(sband
->bitrates
[i
].hw_value
);
303 cmd
->non_ht_rates
= cpu_to_le16(supp
);
304 cmd
->mode
= IWL_TLC_MNG_MODE_NON_HT
;
307 if (he_cap
->has_he
) {
308 cmd
->mode
= IWL_TLC_MNG_MODE_HE
;
309 rs_fw_he_set_enabled_rates(sta
, sband
, cmd
);
310 } else if (vht_cap
->vht_supported
) {
311 cmd
->mode
= IWL_TLC_MNG_MODE_VHT
;
312 rs_fw_vht_set_enabled_rates(sta
, vht_cap
, cmd
);
313 } else if (ht_cap
->ht_supported
) {
314 cmd
->mode
= IWL_TLC_MNG_MODE_HT
;
315 cmd
->ht_rates
[IWL_TLC_NSS_1
][IWL_TLC_HT_BW_NONE_160
] =
316 cpu_to_le16(ht_cap
->mcs
.rx_mask
[0]);
318 /* the station support only a single receive chain */
319 if (sta
->smps_mode
== IEEE80211_SMPS_STATIC
)
320 cmd
->ht_rates
[IWL_TLC_NSS_2
][IWL_TLC_HT_BW_NONE_160
] =
323 cmd
->ht_rates
[IWL_TLC_NSS_2
][IWL_TLC_HT_BW_NONE_160
] =
324 cpu_to_le16(ht_cap
->mcs
.rx_mask
[1]);
328 void iwl_mvm_tlc_update_notif(struct iwl_mvm
*mvm
,
329 struct iwl_rx_cmd_buffer
*rxb
)
331 struct iwl_rx_packet
*pkt
= rxb_addr(rxb
);
332 struct iwl_tlc_update_notif
*notif
;
333 struct ieee80211_sta
*sta
;
334 struct iwl_mvm_sta
*mvmsta
;
335 struct iwl_lq_sta_rs_fw
*lq_sta
;
340 notif
= (void *)pkt
->data
;
341 sta
= rcu_dereference(mvm
->fw_id_to_mac_id
[notif
->sta_id
]);
342 if (IS_ERR_OR_NULL(sta
)) {
343 IWL_ERR(mvm
, "Invalid sta id (%d) in FW TLC notification\n",
348 mvmsta
= iwl_mvm_sta_from_mac80211(sta
);
351 IWL_ERR(mvm
, "Invalid sta id (%d) in FW TLC notification\n",
356 flags
= le32_to_cpu(notif
->flags
);
358 lq_sta
= &mvmsta
->lq_sta
.rs_fw
;
360 if (flags
& IWL_TLC_NOTIF_FLAG_RATE
) {
361 char pretty_rate
[100];
362 lq_sta
->last_rate_n_flags
= le32_to_cpu(notif
->rate
);
363 rs_pretty_print_rate(pretty_rate
, sizeof(pretty_rate
),
364 lq_sta
->last_rate_n_flags
);
365 IWL_DEBUG_RATE(mvm
, "new rate: %s\n", pretty_rate
);
368 if (flags
& IWL_TLC_NOTIF_FLAG_AMSDU
&& !mvmsta
->orig_amsdu_len
) {
369 u16 size
= le32_to_cpu(notif
->amsdu_size
);
373 * In debug sta->max_amsdu_len < size
374 * so also check with orig_amsdu_len which holds the original
375 * data before debugfs changed the value
377 if (WARN_ON(sta
->max_amsdu_len
< size
&&
378 mvmsta
->orig_amsdu_len
< size
))
381 mvmsta
->amsdu_enabled
= le32_to_cpu(notif
->amsdu_enabled
);
382 mvmsta
->max_amsdu_len
= size
;
383 sta
->max_rc_amsdu_len
= mvmsta
->max_amsdu_len
;
385 for (i
= 0; i
< IWL_MAX_TID_COUNT
; i
++) {
386 if (mvmsta
->amsdu_enabled
& BIT(i
))
387 sta
->max_tid_amsdu_len
[i
] =
388 iwl_mvm_max_amsdu_size(mvm
, sta
, i
);
391 * Not so elegant, but this will effectively
392 * prevent AMSDU on this TID
394 sta
->max_tid_amsdu_len
[i
] = 1;
398 "AMSDU update. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n",
399 le32_to_cpu(notif
->amsdu_size
), size
,
400 mvmsta
->amsdu_enabled
);
406 u16
rs_fw_get_max_amsdu_len(struct ieee80211_sta
*sta
)
408 const struct ieee80211_sta_vht_cap
*vht_cap
= &sta
->vht_cap
;
409 const struct ieee80211_sta_ht_cap
*ht_cap
= &sta
->ht_cap
;
411 if (vht_cap
->vht_supported
) {
412 switch (vht_cap
->cap
& IEEE80211_VHT_CAP_MAX_MPDU_MASK
) {
413 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454
:
414 return IEEE80211_MAX_MPDU_LEN_VHT_11454
;
415 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991
:
416 return IEEE80211_MAX_MPDU_LEN_VHT_7991
;
418 return IEEE80211_MAX_MPDU_LEN_VHT_3895
;
420 } else if (ht_cap
->ht_supported
) {
421 if (ht_cap
->cap
& IEEE80211_HT_CAP_MAX_AMSDU
)
423 * agg is offloaded so we need to assume that agg
424 * are enabled and max mpdu in ampdu is 4095
425 * (spec 802.11-2016 9.3.2.1)
427 return IEEE80211_MAX_MPDU_LEN_HT_BA
;
429 return IEEE80211_MAX_MPDU_LEN_HT_3839
;
432 /* in legacy mode no amsdu is enabled so return zero */
436 void rs_fw_rate_init(struct iwl_mvm
*mvm
, struct ieee80211_sta
*sta
,
437 enum nl80211_band band
, bool update
)
439 struct ieee80211_hw
*hw
= mvm
->hw
;
440 struct iwl_mvm_sta
*mvmsta
= iwl_mvm_sta_from_mac80211(sta
);
441 struct iwl_lq_sta_rs_fw
*lq_sta
= &mvmsta
->lq_sta
.rs_fw
;
442 u32 cmd_id
= iwl_cmd_id(TLC_MNG_CONFIG_CMD
, DATA_PATH_GROUP
, 0);
443 struct ieee80211_supported_band
*sband
= hw
->wiphy
->bands
[band
];
444 u16 max_amsdu_len
= rs_fw_get_max_amsdu_len(sta
);
445 struct iwl_tlc_config_cmd cfg_cmd
= {
446 .sta_id
= mvmsta
->sta_id
,
447 .max_ch_width
= update
?
448 rs_fw_bw_from_sta_bw(sta
) : RATE_MCS_CHAN_WIDTH_20
,
449 .flags
= cpu_to_le16(rs_fw_get_config_flags(mvm
, sta
, sband
)),
450 .chains
= rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm
)),
451 .sgi_ch_width_supp
= rs_fw_sgi_cw_support(sta
),
452 .max_mpdu_len
= cpu_to_le16(max_amsdu_len
),
453 .amsdu
= iwl_mvm_is_csum_supported(mvm
),
457 memset(lq_sta
, 0, offsetof(typeof(*lq_sta
), pers
));
459 #ifdef CONFIG_IWLWIFI_DEBUGFS
460 iwl_mvm_reset_frame_stats(mvm
);
462 rs_fw_set_supp_rates(sta
, sband
, &cfg_cmd
);
465 * since TLC offload works with one mode we can assume
466 * that only vht/ht is used and also set it as station max amsdu
468 sta
->max_amsdu_len
= max_amsdu_len
;
470 ret
= iwl_mvm_send_cmd_pdu(mvm
, cmd_id
, CMD_ASYNC
, sizeof(cfg_cmd
),
473 IWL_ERR(mvm
, "Failed to send rate scale config (%d)\n", ret
);
476 int rs_fw_tx_protection(struct iwl_mvm
*mvm
, struct iwl_mvm_sta
*mvmsta
,
479 /* TODO: need to introduce a new FW cmd since LQ cmd is not relevant */
480 IWL_DEBUG_RATE(mvm
, "tx protection - not implemented yet.\n");
484 void iwl_mvm_rs_add_sta(struct iwl_mvm
*mvm
, struct iwl_mvm_sta
*mvmsta
)
486 struct iwl_lq_sta_rs_fw
*lq_sta
= &mvmsta
->lq_sta
.rs_fw
;
488 IWL_DEBUG_RATE(mvm
, "create station rate scale window\n");
490 lq_sta
->pers
.drv
= mvm
;
491 lq_sta
->pers
.sta_id
= mvmsta
->sta_id
;
492 lq_sta
->pers
.chains
= 0;
493 memset(lq_sta
->pers
.chain_signal
, 0, sizeof(lq_sta
->pers
.chain_signal
));
494 lq_sta
->pers
.last_rssi
= S8_MIN
;
495 lq_sta
->last_rate_n_flags
= 0;
497 #ifdef CONFIG_MAC80211_DEBUGFS
498 lq_sta
->pers
.dbg_fixed_rate
= 0;