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 - 2019 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 - 2019 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 our LDPC support in case of HE */
151 if (sband
->iftype_data
&& sband
->iftype_data
->he_cap
.has_he
&&
152 !(sband
->iftype_data
->he_cap
.he_cap_elem
.phy_cap_info
[1] &
153 IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD
))
154 flags
&= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK
;
156 if (he_cap
->has_he
&&
157 (he_cap
->he_cap_elem
.phy_cap_info
[3] &
158 IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK
))
159 flags
|= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK
;
165 int rs_fw_vht_highest_rx_mcs_index(const struct ieee80211_sta_vht_cap
*vht_cap
,
168 u16 rx_mcs
= le16_to_cpu(vht_cap
->vht_mcs
.rx_mcs_map
) &
169 (0x3 << (2 * (nss
- 1)));
170 rx_mcs
>>= (2 * (nss
- 1));
173 case IEEE80211_VHT_MCS_SUPPORT_0_7
:
174 return IWL_TLC_MNG_HT_RATE_MCS7
;
175 case IEEE80211_VHT_MCS_SUPPORT_0_8
:
176 return IWL_TLC_MNG_HT_RATE_MCS8
;
177 case IEEE80211_VHT_MCS_SUPPORT_0_9
:
178 return IWL_TLC_MNG_HT_RATE_MCS9
;
188 rs_fw_vht_set_enabled_rates(const struct ieee80211_sta
*sta
,
189 const struct ieee80211_sta_vht_cap
*vht_cap
,
190 struct iwl_tlc_config_cmd
*cmd
)
195 for (i
= 0; i
< sta
->rx_nss
; i
++) {
196 if (i
== IWL_TLC_NSS_MAX
)
199 highest_mcs
= rs_fw_vht_highest_rx_mcs_index(vht_cap
, i
+ 1);
203 supp
= BIT(highest_mcs
+ 1) - 1;
204 if (sta
->bandwidth
== IEEE80211_STA_RX_BW_20
)
205 supp
&= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9
);
207 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_NONE_160
] = cpu_to_le16(supp
);
208 if (sta
->bandwidth
== IEEE80211_STA_RX_BW_160
)
209 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_160
] =
210 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_NONE_160
];
214 static u16
rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs
)
217 case IEEE80211_HE_MCS_SUPPORT_0_7
:
218 return BIT(IWL_TLC_MNG_HT_RATE_MCS7
+ 1) - 1;
219 case IEEE80211_HE_MCS_SUPPORT_0_9
:
220 return BIT(IWL_TLC_MNG_HT_RATE_MCS9
+ 1) - 1;
221 case IEEE80211_HE_MCS_SUPPORT_0_11
:
222 return BIT(IWL_TLC_MNG_HT_RATE_MCS11
+ 1) - 1;
223 case IEEE80211_HE_MCS_NOT_SUPPORTED
:
227 WARN(1, "invalid HE MCS %d\n", mcs
);
232 rs_fw_he_set_enabled_rates(const struct ieee80211_sta
*sta
,
233 struct ieee80211_supported_band
*sband
,
234 struct iwl_tlc_config_cmd
*cmd
)
236 const struct ieee80211_sta_he_cap
*he_cap
= &sta
->he_cap
;
237 u16 mcs_160
= le16_to_cpu(he_cap
->he_mcs_nss_supp
.rx_mcs_160
);
238 u16 mcs_80
= le16_to_cpu(he_cap
->he_mcs_nss_supp
.rx_mcs_80
);
240 le16_to_cpu(sband
->iftype_data
->he_cap
.he_mcs_nss_supp
.tx_mcs_80
);
242 le16_to_cpu(sband
->iftype_data
->he_cap
.he_mcs_nss_supp
.tx_mcs_160
);
245 for (i
= 0; i
< sta
->rx_nss
&& i
< IWL_TLC_NSS_MAX
; i
++) {
246 u16 _mcs_160
= (mcs_160
>> (2 * i
)) & 0x3;
247 u16 _mcs_80
= (mcs_80
>> (2 * i
)) & 0x3;
248 u16 _tx_mcs_160
= (tx_mcs_160
>> (2 * i
)) & 0x3;
249 u16 _tx_mcs_80
= (tx_mcs_80
>> (2 * i
)) & 0x3;
251 /* If one side doesn't support - mark both as not supporting */
252 if (_mcs_80
== IEEE80211_HE_MCS_NOT_SUPPORTED
||
253 _tx_mcs_80
== IEEE80211_HE_MCS_NOT_SUPPORTED
) {
254 _mcs_80
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
255 _tx_mcs_80
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
257 if (_mcs_80
> _tx_mcs_80
)
258 _mcs_80
= _tx_mcs_80
;
259 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_NONE_160
] =
260 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80
));
262 /* If one side doesn't support - mark both as not supporting */
263 if (_mcs_160
== IEEE80211_HE_MCS_NOT_SUPPORTED
||
264 _tx_mcs_160
== IEEE80211_HE_MCS_NOT_SUPPORTED
) {
265 _mcs_160
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
266 _tx_mcs_160
= IEEE80211_HE_MCS_NOT_SUPPORTED
;
268 if (_mcs_160
> _tx_mcs_160
)
269 _mcs_160
= _tx_mcs_160
;
270 cmd
->ht_rates
[i
][IWL_TLC_HT_BW_160
] =
271 cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160
));
275 static void rs_fw_set_supp_rates(struct ieee80211_sta
*sta
,
276 struct ieee80211_supported_band
*sband
,
277 struct iwl_tlc_config_cmd
*cmd
)
281 unsigned long supp
; /* must be unsigned long for for_each_set_bit */
282 const struct ieee80211_sta_ht_cap
*ht_cap
= &sta
->ht_cap
;
283 const struct ieee80211_sta_vht_cap
*vht_cap
= &sta
->vht_cap
;
284 const struct ieee80211_sta_he_cap
*he_cap
= &sta
->he_cap
;
288 tmp
= sta
->supp_rates
[sband
->band
];
289 for_each_set_bit(i
, &tmp
, BITS_PER_LONG
)
290 supp
|= BIT(sband
->bitrates
[i
].hw_value
);
292 cmd
->non_ht_rates
= cpu_to_le16(supp
);
293 cmd
->mode
= IWL_TLC_MNG_MODE_NON_HT
;
296 if (he_cap
->has_he
) {
297 cmd
->mode
= IWL_TLC_MNG_MODE_HE
;
298 rs_fw_he_set_enabled_rates(sta
, sband
, cmd
);
299 } else if (vht_cap
->vht_supported
) {
300 cmd
->mode
= IWL_TLC_MNG_MODE_VHT
;
301 rs_fw_vht_set_enabled_rates(sta
, vht_cap
, cmd
);
302 } else if (ht_cap
->ht_supported
) {
303 cmd
->mode
= IWL_TLC_MNG_MODE_HT
;
304 cmd
->ht_rates
[IWL_TLC_NSS_1
][IWL_TLC_HT_BW_NONE_160
] =
305 cpu_to_le16(ht_cap
->mcs
.rx_mask
[0]);
306 cmd
->ht_rates
[IWL_TLC_NSS_2
][IWL_TLC_HT_BW_NONE_160
] =
307 cpu_to_le16(ht_cap
->mcs
.rx_mask
[1]);
311 void iwl_mvm_tlc_update_notif(struct iwl_mvm
*mvm
,
312 struct iwl_rx_cmd_buffer
*rxb
)
314 struct iwl_rx_packet
*pkt
= rxb_addr(rxb
);
315 struct iwl_tlc_update_notif
*notif
;
316 struct ieee80211_sta
*sta
;
317 struct iwl_mvm_sta
*mvmsta
;
318 struct iwl_lq_sta_rs_fw
*lq_sta
;
323 notif
= (void *)pkt
->data
;
324 sta
= rcu_dereference(mvm
->fw_id_to_mac_id
[notif
->sta_id
]);
325 if (IS_ERR_OR_NULL(sta
)) {
326 IWL_ERR(mvm
, "Invalid sta id (%d) in FW TLC notification\n",
331 mvmsta
= iwl_mvm_sta_from_mac80211(sta
);
334 IWL_ERR(mvm
, "Invalid sta id (%d) in FW TLC notification\n",
339 flags
= le32_to_cpu(notif
->flags
);
341 lq_sta
= &mvmsta
->lq_sta
.rs_fw
;
343 if (flags
& IWL_TLC_NOTIF_FLAG_RATE
) {
344 char pretty_rate
[100];
345 lq_sta
->last_rate_n_flags
= le32_to_cpu(notif
->rate
);
346 rs_pretty_print_rate(pretty_rate
, sizeof(pretty_rate
),
347 lq_sta
->last_rate_n_flags
);
348 IWL_DEBUG_RATE(mvm
, "new rate: %s\n", pretty_rate
);
351 if (flags
& IWL_TLC_NOTIF_FLAG_AMSDU
&& !mvmsta
->orig_amsdu_len
) {
352 u16 size
= le32_to_cpu(notif
->amsdu_size
);
356 * In debug sta->max_amsdu_len < size
357 * so also check with orig_amsdu_len which holds the original
358 * data before debugfs changed the value
360 if (WARN_ON(sta
->max_amsdu_len
< size
&&
361 mvmsta
->orig_amsdu_len
< size
))
364 mvmsta
->amsdu_enabled
= le32_to_cpu(notif
->amsdu_enabled
);
365 mvmsta
->max_amsdu_len
= size
;
366 sta
->max_rc_amsdu_len
= mvmsta
->max_amsdu_len
;
368 for (i
= 0; i
< IWL_MAX_TID_COUNT
; i
++) {
369 if (mvmsta
->amsdu_enabled
& BIT(i
))
370 sta
->max_tid_amsdu_len
[i
] =
371 iwl_mvm_max_amsdu_size(mvm
, sta
, i
);
374 * Not so elegant, but this will effectively
375 * prevent AMSDU on this TID
377 sta
->max_tid_amsdu_len
[i
] = 1;
381 "AMSDU update. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n",
382 le32_to_cpu(notif
->amsdu_size
), size
,
383 mvmsta
->amsdu_enabled
);
389 u16
rs_fw_get_max_amsdu_len(struct ieee80211_sta
*sta
)
391 const struct ieee80211_sta_vht_cap
*vht_cap
= &sta
->vht_cap
;
392 const struct ieee80211_sta_ht_cap
*ht_cap
= &sta
->ht_cap
;
394 if (vht_cap
->vht_supported
) {
395 switch (vht_cap
->cap
& IEEE80211_VHT_CAP_MAX_MPDU_MASK
) {
396 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454
:
397 return IEEE80211_MAX_MPDU_LEN_VHT_11454
;
398 case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991
:
399 return IEEE80211_MAX_MPDU_LEN_VHT_7991
;
401 return IEEE80211_MAX_MPDU_LEN_VHT_3895
;
404 } else if (ht_cap
->ht_supported
) {
405 if (ht_cap
->cap
& IEEE80211_HT_CAP_MAX_AMSDU
)
407 * agg is offloaded so we need to assume that agg
408 * are enabled and max mpdu in ampdu is 4095
409 * (spec 802.11-2016 9.3.2.1)
411 return IEEE80211_MAX_MPDU_LEN_HT_BA
;
413 return IEEE80211_MAX_MPDU_LEN_HT_3839
;
416 /* in legacy mode no amsdu is enabled so return zero */
420 void rs_fw_rate_init(struct iwl_mvm
*mvm
, struct ieee80211_sta
*sta
,
421 enum nl80211_band band
, bool update
)
423 struct ieee80211_hw
*hw
= mvm
->hw
;
424 struct iwl_mvm_sta
*mvmsta
= iwl_mvm_sta_from_mac80211(sta
);
425 struct iwl_lq_sta_rs_fw
*lq_sta
= &mvmsta
->lq_sta
.rs_fw
;
426 u32 cmd_id
= iwl_cmd_id(TLC_MNG_CONFIG_CMD
, DATA_PATH_GROUP
, 0);
427 struct ieee80211_supported_band
*sband
= hw
->wiphy
->bands
[band
];
428 u16 max_amsdu_len
= rs_fw_get_max_amsdu_len(sta
);
429 struct iwl_tlc_config_cmd cfg_cmd
= {
430 .sta_id
= mvmsta
->sta_id
,
431 .max_ch_width
= update
?
432 rs_fw_bw_from_sta_bw(sta
) : RATE_MCS_CHAN_WIDTH_20
,
433 .flags
= cpu_to_le16(rs_fw_get_config_flags(mvm
, sta
, sband
)),
434 .chains
= rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm
)),
435 .sgi_ch_width_supp
= rs_fw_sgi_cw_support(sta
),
436 .max_mpdu_len
= cpu_to_le16(max_amsdu_len
),
437 .amsdu
= iwl_mvm_is_csum_supported(mvm
),
441 memset(lq_sta
, 0, offsetof(typeof(*lq_sta
), pers
));
443 #ifdef CONFIG_IWLWIFI_DEBUGFS
444 iwl_mvm_reset_frame_stats(mvm
);
446 rs_fw_set_supp_rates(sta
, sband
, &cfg_cmd
);
449 * since TLC offload works with one mode we can assume
450 * that only vht/ht is used and also set it as station max amsdu
452 sta
->max_amsdu_len
= max_amsdu_len
;
454 ret
= iwl_mvm_send_cmd_pdu(mvm
, cmd_id
, CMD_ASYNC
, sizeof(cfg_cmd
),
457 IWL_ERR(mvm
, "Failed to send rate scale config (%d)\n", ret
);
460 int rs_fw_tx_protection(struct iwl_mvm
*mvm
, struct iwl_mvm_sta
*mvmsta
,
463 /* TODO: need to introduce a new FW cmd since LQ cmd is not relevant */
464 IWL_DEBUG_RATE(mvm
, "tx protection - not implemented yet.\n");
468 void iwl_mvm_rs_add_sta(struct iwl_mvm
*mvm
, struct iwl_mvm_sta
*mvmsta
)
470 struct iwl_lq_sta_rs_fw
*lq_sta
= &mvmsta
->lq_sta
.rs_fw
;
472 IWL_DEBUG_RATE(mvm
, "create station rate scale window\n");
474 lq_sta
->pers
.drv
= mvm
;
475 lq_sta
->pers
.sta_id
= mvmsta
->sta_id
;
476 lq_sta
->pers
.chains
= 0;
477 memset(lq_sta
->pers
.chain_signal
, 0, sizeof(lq_sta
->pers
.chain_signal
));
478 lq_sta
->pers
.last_rssi
= S8_MIN
;
479 lq_sta
->last_rate_n_flags
= 0;
481 #ifdef CONFIG_MAC80211_DEBUGFS
482 lq_sta
->pers
.dbg_fixed_rate
= 0;