diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c index 40d790b36d85..1dc974e2c511 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /****************************************************************************** * - * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2014, 2022 Intel Corporation. All rights reserved. *****************************************************************************/ #include #include @@ -441,7 +441,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) priv->current_ht_config.smps = smps_request; for_each_context(priv, ctx) { if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) - ieee80211_request_smps(ctx->vif, smps_request); + ieee80211_request_smps(ctx->vif, 0, smps_request); } } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 3ee5ea3484be..14b2de65bd84 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -304,7 +304,7 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, smps_mode = IEEE80211_SMPS_DYNAMIC; } - ieee80211_request_smps(vif, smps_mode); + ieee80211_request_smps(vif, 0, smps_mode); } static bool iwl_wait_stats_complete(struct iwl_notif_wait_data *notif_wait, diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index f78b9f28d5f6..985ee36efc0f 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1600,9 +1600,9 @@ static void rtw_vif_smps_iter(void *data, u8 *mac, return; if (rtwdev->hal.txrx_1ss) - ieee80211_request_smps(vif, IEEE80211_SMPS_STATIC); + ieee80211_request_smps(vif, 0, IEEE80211_SMPS_STATIC); else - ieee80211_request_smps(vif, IEEE80211_SMPS_OFF); + ieee80211_request_smps(vif, 0, IEEE80211_SMPS_OFF); } void rtw_set_txrx_1ss(struct rtw_dev *rtwdev, bool txrx_1ss) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 0a26cb2871d6..302340f6fa08 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -6210,13 +6210,14 @@ void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, /** * ieee80211_request_smps - request SM PS transition * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @link_id: link ID for MLO, or 0 * @smps_mode: new SM PS mode * * This allows the driver to request an SM PS transition in managed * mode. This is useful when the driver has more information than * the stack about possible interference, for example by bluetooth. */ -void ieee80211_request_smps(struct ieee80211_vif *vif, +void ieee80211_request_smps(struct ieee80211_vif *vif, unsigned int link_id, enum ieee80211_smps_mode smps_mode); /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d7f2eb7421c3..2c9554174bcf 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2913,6 +2913,7 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy, #endif int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, + unsigned int link_id, enum ieee80211_smps_mode smps_mode) { const u8 *ap; @@ -2926,8 +2927,8 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION)) return -EINVAL; - old_req = sdata->deflink.u.mgd.req_smps; - sdata->deflink.u.mgd.req_smps = smps_mode; + old_req = sdata->link[link_id]->u.mgd.req_smps; + sdata->link[link_id]->u.mgd.req_smps = smps_mode; if (old_req == smps_mode && smps_mode != IEEE80211_SMPS_AUTOMATIC) @@ -2939,10 +2940,10 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, * the new value until we associate. */ if (!sdata->u.mgd.associated || - sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) + sdata->vif.link_conf[link_id]->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) return 0; - ap = sdata->deflink.u.mgd.bssid; + ap = sdata->link[link_id]->u.mgd.bssid; rcu_read_lock(); list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) { @@ -2966,7 +2967,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, err = ieee80211_send_smps_action(sdata, smps_mode, ap, ap); if (err) - sdata->deflink.u.mgd.req_smps = old_req; + sdata->link[link_id]->u.mgd.req_smps = old_req; else if (smps_mode != IEEE80211_SMPS_OFF && tdls_peer_found) ieee80211_teardown_tdls_peers(sdata); @@ -2978,6 +2979,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + unsigned int link_id; if (sdata->vif.type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; @@ -2994,7 +2996,12 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, /* no change, but if automatic follow powersave */ sdata_lock(sdata); - __ieee80211_request_smps_mgd(sdata, sdata->deflink.u.mgd.req_smps); + for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) { + if (!sdata->link[link_id]) + continue; + __ieee80211_request_smps_mgd(sdata, link_id, + sdata->link[link_id]->u.mgd.req_smps); + } sdata_unlock(sdata); if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS)) diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index bd398b631763..dfb194e15018 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -256,7 +256,7 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, return -EOPNOTSUPP; sdata_lock(sdata); - err = __ieee80211_request_smps_mgd(sdata, smps_mode); + err = __ieee80211_request_smps_mgd(sdata, 0, smps_mode); sdata_unlock(sdata); return err; diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 22677df83ed8..111828b559a0 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -542,30 +542,33 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, void ieee80211_request_smps_mgd_work(struct work_struct *work) { - struct ieee80211_sub_if_data *sdata = - container_of(work, struct ieee80211_sub_if_data, - deflink.u.mgd.request_smps_work); + struct ieee80211_link_data *link = + container_of(work, struct ieee80211_link_data, + u.mgd.request_smps_work); - sdata_lock(sdata); - __ieee80211_request_smps_mgd(sdata, - sdata->deflink.u.mgd.driver_smps_mode); - sdata_unlock(sdata); + sdata_lock(link->sdata); + __ieee80211_request_smps_mgd(link->sdata, link->link_id, + link->u.mgd.driver_smps_mode); + sdata_unlock(link->sdata); } -void ieee80211_request_smps(struct ieee80211_vif *vif, +void ieee80211_request_smps(struct ieee80211_vif *vif, unsigned int link_id, enum ieee80211_smps_mode smps_mode) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_link_data *link = sdata->link[link_id]; if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION)) return; - if (sdata->deflink.u.mgd.driver_smps_mode == smps_mode) + if (WARN_ON(!link)) return; - sdata->deflink.u.mgd.driver_smps_mode = smps_mode; - ieee80211_queue_work(&sdata->local->hw, - &sdata->deflink.u.mgd.request_smps_work); + if (link->u.mgd.driver_smps_mode == smps_mode) + return; + + link->u.mgd.driver_smps_mode = smps_mode; + ieee80211_queue_work(&sdata->local->hw, &link->u.mgd.request_smps_work); } /* this might change ... don't want non-open drivers using it */ EXPORT_SYMBOL_GPL(ieee80211_request_smps); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e75496a99299..0948d074c4b9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2422,8 +2422,10 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, struct ieee802_11_elems *elems, enum nl80211_band band, u32 *basic_rates); int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, + unsigned int link_id, enum ieee80211_smps_mode smps_mode); -void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata); +void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata, + unsigned int link_id); void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata); size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index c5be60ee12d8..ea75d5d5cb6a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1657,7 +1657,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work) struct ieee80211_sub_if_data *sdata = container_of(work, struct ieee80211_sub_if_data, recalc_smps); - ieee80211_recalc_smps(sdata); + ieee80211_recalc_smps(sdata, 0); } /* diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 30423b2d4eee..cdbf7a5dc2ba 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2337,7 +2337,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_recalc_ps(local); mutex_unlock(&local->iflist_mtx); - ieee80211_recalc_smps(sdata); + ieee80211_recalc_smps(sdata, 0); ieee80211_recalc_ps_vif(sdata); netif_carrier_on(sdata->dev); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 4ec96170a679..ecda655e7481 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2803,7 +2803,8 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif) } EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect); -void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata) +void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata, + unsigned int link_id) { struct ieee80211_local *local = sdata->local; struct ieee80211_chanctx_conf *chanctx_conf; @@ -2811,7 +2812,7 @@ void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata) mutex_lock(&local->chanctx_mtx); - chanctx_conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf, + chanctx_conf = rcu_dereference_protected(sdata->vif.link_conf[link_id]->chanctx_conf, lockdep_is_held(&local->chanctx_mtx)); /*