Skip to content

Commit 12bacfc

Browse files
Miriam-Racheljmberg-intel
authored andcommitted
wifi: iwlwifi: handle eSR transitions
There several transitions to handle in eSR mode: * SMPS should be disabled when in eSR mode * indicate to the fw whether the new added link should use the listen lmac or the main lmac * RLC is offloaded when in eSR mode; adjust RLC command accordingly Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230615094410.fb6409f44aca.I502460dec15e0b76035ad3cd809afa4ac16e9fe1@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent 823a970 commit 12bacfc

File tree

5 files changed

+155
-33
lines changed

5 files changed

+155
-33
lines changed

drivers/net/wireless/intel/iwlwifi/mvm/link.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
8989
if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
9090
memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);
9191

92+
cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac);
93+
9294
return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD);
9395
}
9496

@@ -149,10 +151,6 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
149151
if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
150152
memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);
151153

152-
/* TODO: set a value to cmd.listen_lmac when system requiremens
153-
* will define it
154-
*/
155-
156154
iwl_mvm_set_fw_basic_rates(mvm, vif, link_conf,
157155
&cmd.cck_rates, &cmd.ofdm_rates);
158156

@@ -228,6 +226,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
228226
cmd.flags = cpu_to_le32(flags);
229227
cmd.flags_mask = cpu_to_le32(flags_mask);
230228
cmd.spec_link_id = link_conf->link_id;
229+
cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac);
231230

232231
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY);
233232
if (!ret && (changes & LINK_CONTEXT_MODIFY_ACTIVE))

drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c

Lines changed: 128 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,53 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
215215
mutex_unlock(&mvm->mutex);
216216
}
217217

218+
static unsigned int iwl_mvm_mld_count_active_links(struct ieee80211_vif *vif)
219+
{
220+
unsigned int n_active = 0;
221+
int i;
222+
223+
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
224+
struct ieee80211_bss_conf *link_conf;
225+
226+
link_conf = link_conf_dereference_protected(vif, i);
227+
if (link_conf &&
228+
rcu_access_pointer(link_conf->chanctx_conf))
229+
n_active++;
230+
}
231+
232+
return n_active;
233+
}
234+
235+
static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
236+
struct ieee80211_vif *vif)
237+
{
238+
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
239+
int link_id, ret = 0;
240+
241+
mvmvif->esr_active = true;
242+
243+
/* Disable SMPS overrideing by user */
244+
vif->driver_flags |= IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
245+
246+
iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
247+
IEEE80211_SMPS_OFF);
248+
249+
for_each_mvm_vif_valid_link(mvmvif, link_id) {
250+
struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
251+
252+
if (!link->phy_ctxt)
253+
continue;
254+
255+
ret = iwl_mvm_phy_send_rlc(mvm, link->phy_ctxt, 2, 2);
256+
if (ret)
257+
break;
258+
259+
link->phy_ctxt->rlc_disabled = true;
260+
}
261+
262+
return ret;
263+
}
264+
218265
static int
219266
__iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
220267
struct ieee80211_vif *vif,
@@ -224,10 +271,18 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
224271
{
225272
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
226273
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
274+
unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
227275
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
228276
unsigned int link_id = link_conf->link_id;
229277
int ret;
230278

279+
/* if the assigned one was not counted yet, count it now */
280+
if (!rcu_access_pointer(link_conf->chanctx_conf))
281+
n_active++;
282+
283+
if (n_active > iwl_mvm_max_active_links(mvm, vif))
284+
return -EOPNOTSUPP;
285+
231286
if (WARN_ON_ONCE(!mvmvif->link[link_id]))
232287
return -EINVAL;
233288

@@ -243,6 +298,15 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
243298
}
244299
}
245300

301+
if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
302+
mvmvif->link[link_id]->listen_lmac = true;
303+
ret = iwl_mvm_esr_mode_active(mvm, vif);
304+
if (ret) {
305+
IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret);
306+
return ret;
307+
}
308+
}
309+
246310
mvmvif->link[link_id]->phy_ctxt = phy_ctxt;
247311

248312
if (switching_chanctx) {
@@ -326,14 +390,62 @@ static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
326390
return ret;
327391
}
328392

393+
static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm,
394+
struct ieee80211_vif *vif)
395+
{
396+
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
397+
struct ieee80211_bss_conf *link_conf;
398+
int link_id, ret = 0;
399+
400+
mvmvif->esr_active = false;
401+
402+
vif->driver_flags &= ~IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
403+
404+
iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
405+
IEEE80211_SMPS_AUTOMATIC);
406+
407+
for_each_vif_active_link(vif, link_conf, link_id) {
408+
struct ieee80211_chanctx_conf *chanctx_conf;
409+
struct iwl_mvm_phy_ctxt *phy_ctxt;
410+
u8 static_chains, dynamic_chains;
411+
412+
mvmvif->link[link_id]->listen_lmac = false;
413+
414+
rcu_read_lock();
415+
416+
chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
417+
phy_ctxt = mvmvif->link[link_id]->phy_ctxt;
418+
419+
if (!chanctx_conf || !phy_ctxt) {
420+
rcu_read_unlock();
421+
continue;
422+
}
423+
424+
phy_ctxt->rlc_disabled = false;
425+
static_chains = chanctx_conf->rx_chains_static;
426+
dynamic_chains = chanctx_conf->rx_chains_dynamic;
427+
428+
rcu_read_unlock();
429+
430+
ret = iwl_mvm_phy_send_rlc(mvm, phy_ctxt, static_chains,
431+
dynamic_chains);
432+
if (ret)
433+
break;
434+
}
435+
436+
return ret;
437+
}
438+
329439
static void
330440
__iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
331441
struct ieee80211_vif *vif,
332442
struct ieee80211_bss_conf *link_conf,
333443
struct ieee80211_chanctx_conf *ctx,
334444
bool switching_chanctx)
445+
335446
{
336447
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
448+
unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
337449
unsigned int link_id = link_conf->link_id;
338450

339451
/* shouldn't happen, but verify link_id is valid before accessing */
@@ -352,6 +464,14 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
352464
mvmvif->ap_ibss_active = false;
353465
}
354466

467+
if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
468+
int ret = iwl_mvm_esr_mode_inactive(mvm, vif);
469+
470+
if (ret)
471+
IWL_ERR(mvm, "failed to deactivate ESR mode (%d)\n",
472+
ret);
473+
}
474+
355475
if (vif->type == NL80211_IFTYPE_MONITOR)
356476
iwl_mvm_mld_rm_snif_sta(mvm, vif);
357477

@@ -894,31 +1014,16 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
8941014
struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
8951015
{
8961016
struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
1017+
unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
8971018
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
8981019
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
8991020
u16 removed = old_links & ~new_links;
9001021
u16 added = new_links & ~old_links;
9011022
int err, i;
9021023

903-
if (hweight16(new_links) > 1) {
904-
unsigned int n_active = 0;
905-
906-
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
907-
struct ieee80211_bss_conf *link_conf;
908-
909-
link_conf = link_conf_dereference_protected(vif, i);
910-
if (link_conf &&
911-
rcu_access_pointer(link_conf->chanctx_conf))
912-
n_active++;
913-
}
914-
915-
if (vif->type == NL80211_IFTYPE_AP) {
916-
if (n_active > mvm->fw->ucode_capa.num_beacons)
917-
return -EOPNOTSUPP;
918-
} else if (n_active > iwl_mvm_max_active_links(mvm)) {
919-
return -EOPNOTSUPP;
920-
}
921-
}
1024+
if (hweight16(new_links) > 1 &&
1025+
n_active > iwl_mvm_max_active_links(mvm, vif))
1026+
return -EOPNOTSUPP;
9221027

9231028
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
9241029
int r;
@@ -962,9 +1067,7 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
9621067
goto out_err;
9631068
kfree(mvmvif->link[i]);
9641069
mvmvif->link[i] = NULL;
965-
}
966-
967-
if (added & BIT(i)) {
1070+
} else if (added & BIT(i)) {
9681071
struct ieee80211_bss_conf *link_conf;
9691072

9701073
link_conf = link_conf_dereference_protected(vif, i);
@@ -981,6 +1084,9 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
9811084
}
9821085
}
9831086

1087+
if (err)
1088+
goto out_err;
1089+
9841090
err = 0;
9851091
if (new_links == 0) {
9861092
mvmvif->link[0] = &mvmvif->deflink;

drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ struct iwl_mvm_phy_ctxt {
104104

105105
/* track for RLC config command */
106106
u32 center_freq1;
107+
bool rlc_disabled;
107108
};
108109

109110
struct iwl_mvm_time_event_data {
@@ -301,6 +302,7 @@ struct iwl_probe_resp_data {
301302
* @queue_params: QoS params for this MAC
302303
* @mgmt_queue: queue number for unbufferable management frames
303304
* @igtk: the current IGTK programmed into the firmware
305+
* @listen_lmac: indicates this link is allocated to the listen LMAC
304306
*/
305307
struct iwl_mvm_vif_link_info {
306308
u8 bssid[ETH_ALEN];
@@ -322,6 +324,7 @@ struct iwl_mvm_vif_link_info {
322324

323325
bool he_ru_2mhz_block;
324326
bool active;
327+
bool listen_lmac;
325328

326329
u16 cab_queue;
327330
/* Assigned while mac80211 has the link in a channel context,
@@ -373,6 +376,7 @@ struct iwl_mvm_vif {
373376
bool ap_ibss_active;
374377
bool pm_enabled;
375378
bool monitor_active;
379+
bool esr_active;
376380

377381
u8 low_latency: 6;
378382
u8 low_latency_actual: 1;
@@ -1554,10 +1558,14 @@ static inline bool iwl_mvm_is_esr_supported(struct iwl_trans *trans)
15541558
return false;
15551559
}
15561560

1557-
static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm)
1561+
static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm,
1562+
struct ieee80211_vif *vif)
15581563
{
15591564
struct iwl_trans *trans = mvm->fwrt.trans;
15601565

1566+
if (vif->type == NL80211_IFTYPE_AP)
1567+
return mvm->fw->ucode_capa.num_beacons;
1568+
15611569
if (iwl_mvm_is_esr_supported(trans) ||
15621570
(CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM &&
15631571
CSR_HW_RFID_IS_CDB(trans->hw_rf_id)))
@@ -1777,6 +1785,8 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
17771785
int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
17781786
u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef);
17791787
u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef);
1788+
int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
1789+
u8 chains_static, u8 chains_dynamic);
17801790

17811791
/* MAC (virtual interface) programming */
17821792

drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22
/*
3-
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
3+
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
44
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
55
* Copyright (C) 2017 Intel Deutschland GmbH
66
*/
@@ -163,15 +163,18 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
163163
chains_static, chains_dynamic);
164164
}
165165

166-
static int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm,
167-
struct iwl_mvm_phy_ctxt *ctxt,
168-
u8 chains_static, u8 chains_dynamic)
166+
int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
167+
u8 chains_static, u8 chains_dynamic)
169168
{
170169
struct iwl_rlc_config_cmd cmd = {
171170
.phy_id = cpu_to_le32(ctxt->id),
172171
};
173172

174-
if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP, RLC_CONFIG_CMD), 0) < 2)
173+
if (ctxt->rlc_disabled)
174+
return 0;
175+
176+
if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP,
177+
RLC_CONFIG_CMD), 0) < 2)
175178
return 0;
176179

177180
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_DRIVER_FORCE !=

drivers/net/wireless/intel/iwlwifi/mvm/utils.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22
/*
3-
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
3+
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
44
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
55
* Copyright (C) 2015-2017 Intel Deutschland GmbH
66
*/
@@ -312,6 +312,10 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
312312
smps_mode = IEEE80211_SMPS_DYNAMIC;
313313
}
314314

315+
/* SMPS is disabled in eSR */
316+
if (mvmvif->esr_active)
317+
smps_mode = IEEE80211_SMPS_OFF;
318+
315319
ieee80211_request_smps(vif, link_id, smps_mode);
316320
}
317321

0 commit comments

Comments
 (0)