Commit 84ef7cbe authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg

wifi: iwlwifi: mvm: Don't always bind/link the P2P Device interface

It is not necessary to keep the P2P Device bound/linked to a PHY
context when there is no active ROC.

Modify the P2P Device flows so the binding/linking would be done
only while ROC is active. With this change the switch_phy_ctxt()
is no longer needed so remove it.
Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20231004123422.c5b83b4bf9de.Ia80daf3ba0b5fec7d0919247fcbdbdb58bddf02b@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 706f1b5d
...@@ -53,7 +53,6 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -53,7 +53,6 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
unsigned int link_id = link_conf->link_id; unsigned int link_id = link_conf->link_id;
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
struct iwl_link_config_cmd cmd = {}; struct iwl_link_config_cmd cmd = {};
struct iwl_mvm_phy_ctxt *phyctxt;
if (WARN_ON_ONCE(!link_info)) if (WARN_ON_ONCE(!link_info))
return -EINVAL; return -EINVAL;
...@@ -77,11 +76,7 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -77,11 +76,7 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cmd.link_id = cpu_to_le32(link_info->fw_link_id); cmd.link_id = cpu_to_le32(link_info->fw_link_id);
cmd.mac_id = cpu_to_le32(mvmvif->id); cmd.mac_id = cpu_to_le32(mvmvif->id);
cmd.spec_link_id = link_conf->link_id; cmd.spec_link_id = link_conf->link_id;
/* P2P-Device already has a valid PHY context during add */ WARN_ON_ONCE(link_info->phy_ctxt);
phyctxt = link_info->phy_ctxt;
if (phyctxt)
cmd.phy_id = cpu_to_le32(phyctxt->id);
else
cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID); cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);
memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN); memcpy(cmd.local_link_addr, link_conf->addr, ETH_ALEN);
......
...@@ -286,6 +286,10 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -286,6 +286,10 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
INIT_LIST_HEAD(&mvmvif->time_event_data.list); INIT_LIST_HEAD(&mvmvif->time_event_data.list);
mvmvif->time_event_data.id = TE_MAX; mvmvif->time_event_data.id = TE_MAX;
mvmvif->deflink.bcast_sta.sta_id = IWL_MVM_INVALID_STA;
mvmvif->deflink.mcast_sta.sta_id = IWL_MVM_INVALID_STA;
mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
/* No need to allocate data queues to P2P Device MAC and NAN.*/ /* No need to allocate data queues to P2P Device MAC and NAN.*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
return 0; return 0;
...@@ -300,10 +304,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -300,10 +304,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE; mvmvif->deflink.cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
} }
mvmvif->deflink.bcast_sta.sta_id = IWL_MVM_INVALID_STA;
mvmvif->deflink.mcast_sta.sta_id = IWL_MVM_INVALID_STA;
mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
mvmvif->deflink.smps_requests[i] = IEEE80211_SMPS_AUTOMATIC; mvmvif->deflink.smps_requests[i] = IEEE80211_SMPS_AUTOMATIC;
......
...@@ -1607,32 +1607,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ...@@ -1607,32 +1607,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI; IEEE80211_VIF_SUPPORTS_CQM_RSSI;
} }
/* if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
* P2P_DEVICE interface does not have a channel context assigned to it,
* so a dedicated PHY context is allocated to it and the corresponding
* MAC context is bound to it at this stage.
*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
mvmvif->deflink.phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
if (!mvmvif->deflink.phy_ctxt) {
ret = -ENOSPC;
goto out_free_bf;
}
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
ret = iwl_mvm_binding_add_vif(mvm, vif);
if (ret)
goto out_unref_phy;
ret = iwl_mvm_add_p2p_bcast_sta(mvm, vif);
if (ret)
goto out_unbind;
/* Save a pointer to p2p device vif, so it can later be used to
* update the p2p device MAC when a GO is started/stopped */
mvm->p2p_device_vif = vif; mvm->p2p_device_vif = vif;
}
iwl_mvm_tcm_add_vif(mvm, vif); iwl_mvm_tcm_add_vif(mvm, vif);
INIT_DELAYED_WORK(&mvmvif->csa_work, INIT_DELAYED_WORK(&mvmvif->csa_work,
...@@ -1661,11 +1637,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ...@@ -1661,11 +1637,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
goto out_unlock; goto out_unlock;
out_unbind:
iwl_mvm_binding_remove_vif(mvm, vif);
out_unref_phy:
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
out_free_bf:
if (mvm->bf_allowed_vif == mvmvif) { if (mvm->bf_allowed_vif == mvmvif) {
mvm->bf_allowed_vif = NULL; mvm->bf_allowed_vif = NULL;
vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER | vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
...@@ -1762,13 +1733,18 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, ...@@ -1762,13 +1733,18 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
if (iwl_mvm_mac_remove_interface_common(hw, vif)) if (iwl_mvm_mac_remove_interface_common(hw, vif))
goto out; goto out;
/* Before the interface removal, mac80211 would cancel the ROC, and the
* ROC worker would be scheduled if needed. The worker would be flushed
* in iwl_mvm_prepare_mac_removal() and thus at this point there is no
* binding etc. so nothing needs to be done here.
*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
mvm->p2p_device_vif = NULL; if (mvmvif->deflink.phy_ctxt) {
iwl_mvm_rm_p2p_bcast_sta(mvm, vif);
iwl_mvm_binding_remove_vif(mvm, vif);
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt); iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
mvmvif->deflink.phy_ctxt = NULL; mvmvif->deflink.phy_ctxt = NULL;
} }
mvm->p2p_device_vif = NULL;
}
iwl_mvm_mac_ctxt_remove(mvm, vif); iwl_mvm_mac_ctxt_remove(mvm, vif);
...@@ -4576,30 +4552,20 @@ static int iwl_mvm_add_aux_sta_for_hs20(struct iwl_mvm *mvm, u32 lmac_id) ...@@ -4576,30 +4552,20 @@ static int iwl_mvm_add_aux_sta_for_hs20(struct iwl_mvm *mvm, u32 lmac_id)
return ret; return ret;
} }
static int iwl_mvm_roc_switch_binding(struct iwl_mvm *mvm, static int iwl_mvm_roc_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct ieee80211_vif *vif,
struct iwl_mvm_phy_ctxt *new_phy_ctxt)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); int ret;
int ret = 0;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
/* Unbind the P2P_DEVICE from the current PHY context,
* and if the PHY context is not used remove it.
*/
ret = iwl_mvm_binding_remove_vif(mvm, vif);
if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
return ret;
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
/* Bind the P2P_DEVICE to the current PHY Context */
mvmvif->deflink.phy_ctxt = new_phy_ctxt;
ret = iwl_mvm_binding_add_vif(mvm, vif); ret = iwl_mvm_binding_add_vif(mvm, vif);
WARN(ret, "Failed binding P2P_DEVICE\n"); if (WARN(ret, "Failed binding P2P_DEVICE\n"))
return ret; return ret;
/* The station and queue allocation must be done only after the binding
* is done, as otherwise the FW might incorrectly configure its state.
*/
return iwl_mvm_add_p2p_bcast_sta(mvm, vif);
} }
static int iwl_mvm_roc(struct ieee80211_hw *hw, static int iwl_mvm_roc(struct ieee80211_hw *hw,
...@@ -4610,7 +4576,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, ...@@ -4610,7 +4576,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
{ {
static const struct iwl_mvm_roc_ops ops = { static const struct iwl_mvm_roc_ops ops = {
.add_aux_sta_for_hs20 = iwl_mvm_add_aux_sta_for_hs20, .add_aux_sta_for_hs20 = iwl_mvm_add_aux_sta_for_hs20,
.switch_phy_ctxt = iwl_mvm_roc_switch_binding, .link = iwl_mvm_roc_link,
}; };
return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops); return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
...@@ -4626,7 +4592,6 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -4626,7 +4592,6 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
struct iwl_mvm_phy_ctxt *phy_ctxt; struct iwl_mvm_phy_ctxt *phy_ctxt;
bool band_change_removal;
int ret, i; int ret, i;
u32 lmac_id; u32 lmac_id;
...@@ -4655,64 +4620,48 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -4655,64 +4620,48 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
/* handle below */ /* handle below */
break; break;
default: default:
IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type); IWL_ERR(mvm, "ROC: Invalid vif type=%u\n", vif->type);
ret = -EINVAL; ret = -EINVAL;
goto out_unlock; goto out_unlock;
} }
/* Try using a PHY context that is already in use */
for (i = 0; i < NUM_PHY_CTX; i++) { for (i = 0; i < NUM_PHY_CTX; i++) {
phy_ctxt = &mvm->phy_ctxts[i]; phy_ctxt = &mvm->phy_ctxts[i];
if (phy_ctxt->ref == 0 || mvmvif->deflink.phy_ctxt == phy_ctxt) if (!phy_ctxt->ref || mvmvif->deflink.phy_ctxt == phy_ctxt)
continue; continue;
if (phy_ctxt->ref && channel == phy_ctxt->channel) { if (channel == phy_ctxt->channel) {
ret = ops->switch_phy_ctxt(mvm, vif, phy_ctxt); if (mvmvif->deflink.phy_ctxt)
if (ret) iwl_mvm_phy_ctxt_unref(mvm,
goto out_unlock; mvmvif->deflink.phy_ctxt);
mvmvif->deflink.phy_ctxt = phy_ctxt;
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt); iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
goto schedule_time_event; goto link_and_start_p2p_roc;
} }
} }
/* Need to update the PHY context only if the ROC channel changed */ /* If the currently used PHY context is configured with a matching
if (channel == mvmvif->deflink.phy_ctxt->channel) * channel use it
goto schedule_time_event;
cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
/*
* Check if the remain-on-channel is on a different band and that
* requires context removal, see iwl_mvm_phy_ctxt_changed(). If
* so, we'll need to release and then re-configure here, since we
* must not remove a PHY context that's part of a binding.
*/
band_change_removal =
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
mvmvif->deflink.phy_ctxt->channel->band != chandef.chan->band;
if (mvmvif->deflink.phy_ctxt->ref == 1 && !band_change_removal) {
/*
* Change the PHY context configuration as it is currently
* referenced only by the P2P Device MAC (and we can modify it)
*/ */
ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->deflink.phy_ctxt, if (mvmvif->deflink.phy_ctxt) {
&chandef, 1, 1); if (channel == mvmvif->deflink.phy_ctxt->channel)
if (ret) goto link_and_start_p2p_roc;
goto out_unlock;
} else { } else {
/*
* The PHY context is shared with other MACs (or we're trying to
* switch bands), so remove the P2P Device from the binding,
* allocate an new PHY context and create a new binding.
*/
phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
if (!phy_ctxt) { if (!phy_ctxt) {
ret = -ENOSPC; ret = -ENOSPC;
goto out_unlock; goto out_unlock;
} }
mvmvif->deflink.phy_ctxt = phy_ctxt;
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
}
/* Configure the PHY context */
cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chandef, ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chandef,
1, 1); 1, 1);
if (ret) { if (ret) {
...@@ -4720,17 +4669,12 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -4720,17 +4669,12 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto out_unlock; goto out_unlock;
} }
ret = ops->switch_phy_ctxt(mvm, vif, phy_ctxt); link_and_start_p2p_roc:
ret = ops->link(mvm, vif);
if (ret) if (ret)
goto out_unlock; goto out_unlock;
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
}
schedule_time_event:
/* Schedule the time events */
ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type); ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type);
out_unlock: out_unlock:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
IWL_DEBUG_MAC80211(mvm, "leave\n"); IWL_DEBUG_MAC80211(mvm, "leave\n");
......
...@@ -56,43 +56,15 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, ...@@ -56,43 +56,15 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI; IEEE80211_VIF_SUPPORTS_CQM_RSSI;
} }
/*
* P2P_DEVICE interface does not have a channel context assigned to it,
* so a dedicated PHY context is allocated to it and the corresponding
* MAC context is bound to it at this stage.
*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
mvmvif->deflink.phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
if (!mvmvif->deflink.phy_ctxt) {
ret = -ENOSPC;
goto out_free_bf;
}
iwl_mvm_phy_ctxt_ref(mvm, mvmvif->deflink.phy_ctxt);
ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf); ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
if (ret) if (ret)
goto out_unref_phy; goto out_free_bf;
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
LINK_CONTEXT_MODIFY_ACTIVE |
LINK_CONTEXT_MODIFY_RATES_INFO,
true);
if (ret)
goto out_remove_link;
ret = iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
if (ret)
goto out_remove_link;
/* Save a pointer to p2p device vif, so it can later be used to /* Save a pointer to p2p device vif, so it can later be used to
* update the p2p device MAC when a GO is started/stopped * update the p2p device MAC when a GO is started/stopped
*/ */
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
mvm->p2p_device_vif = vif; mvm->p2p_device_vif = vif;
} else {
ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
if (ret)
goto out_free_bf;
}
ret = iwl_mvm_power_update_mac(mvm); ret = iwl_mvm_power_update_mac(mvm);
if (ret) if (ret)
...@@ -119,10 +91,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, ...@@ -119,10 +91,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
goto out_unlock; goto out_unlock;
out_remove_link:
iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
out_unref_phy:
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
out_free_bf: out_free_bf:
if (mvm->bf_allowed_vif == mvmvif) { if (mvm->bf_allowed_vif == mvmvif) {
mvm->bf_allowed_vif = NULL; mvm->bf_allowed_vif = NULL;
...@@ -130,7 +98,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, ...@@ -130,7 +98,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI); IEEE80211_VIF_SUPPORTS_CQM_RSSI);
} }
out_remove_mac: out_remove_mac:
mvmvif->deflink.phy_ctxt = NULL;
mvmvif->link[0] = NULL; mvmvif->link[0] = NULL;
iwl_mvm_mld_mac_ctxt_remove(mvm, vif); iwl_mvm_mld_mac_ctxt_remove(mvm, vif);
out_unlock: out_unlock:
...@@ -185,14 +152,18 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw, ...@@ -185,14 +152,18 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
iwl_mvm_power_update_mac(mvm); iwl_mvm_power_update_mac(mvm);
/* Before the interface removal, mac80211 would cancel the ROC, and the
* ROC worker would be scheduled if needed. The worker would be flushed
* in iwl_mvm_prepare_mac_removal() and thus at this point the link is
* not active. So need only to remove the link.
*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
mvm->p2p_device_vif = NULL; if (mvmvif->deflink.phy_ctxt) {
/* P2P device uses only one link */
iwl_mvm_mld_rm_bcast_sta(mvm, vif, &vif->bss_conf);
iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt); iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
mvmvif->deflink.phy_ctxt = NULL; mvmvif->deflink.phy_ctxt = NULL;
}
mvm->p2p_device_vif = NULL;
iwl_mvm_remove_link(mvm, vif, &vif->bss_conf);
} else { } else {
iwl_mvm_disable_link(mvm, vif, &vif->bss_conf); iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
} }
...@@ -1091,36 +1062,29 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw, ...@@ -1091,36 +1062,29 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
return 0; return 0;
} }
static int iwl_mvm_link_switch_phy_ctx(struct iwl_mvm *mvm, static int iwl_mvm_mld_roc_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct ieee80211_vif *vif,
struct iwl_mvm_phy_ctxt *new_phy_ctxt)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); int ret;
int ret = 0;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
/* Inorder to change the phy_ctx of a link, the link needs to be /* The PHY context ID might have changed so need to set it */
* inactive. Therefore, first deactivate the link, then change its
* phy_ctx, and then activate it again.
*/
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
LINK_CONTEXT_MODIFY_ACTIVE, false);
if (WARN(ret, "Failed to deactivate link\n"))
return ret;
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->deflink.phy_ctxt);
mvmvif->deflink.phy_ctxt = new_phy_ctxt;
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false); ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, 0, false);
if (WARN(ret, "Failed to deactivate link\n")) if (WARN(ret, "Failed to set PHY context ID\n"))
return ret; return ret;
ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf, ret = iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
LINK_CONTEXT_MODIFY_ACTIVE, true); LINK_CONTEXT_MODIFY_ACTIVE |
WARN(ret, "Failed binding P2P_DEVICE\n"); LINK_CONTEXT_MODIFY_RATES_INFO,
true);
if (WARN(ret, "Failed linking P2P_DEVICE\n"))
return ret; return ret;
/* The station and queue allocation must be done only after the linking
* is done, as otherwise the FW might incorrectly configure its state.
*/
return iwl_mvm_mld_add_bcast_sta(mvm, vif, &vif->bss_conf);
} }
static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
...@@ -1129,7 +1093,7 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -1129,7 +1093,7 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
{ {
static const struct iwl_mvm_roc_ops ops = { static const struct iwl_mvm_roc_ops ops = {
.add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta, .add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta,
.switch_phy_ctxt = iwl_mvm_link_switch_phy_ctx, .link = iwl_mvm_mld_roc_link,
}; };
return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops); return iwl_mvm_roc_common(hw, vif, channel, duration, type, &ops);
......
...@@ -1971,13 +1971,12 @@ void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm, ...@@ -1971,13 +1971,12 @@ void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
* *
* @add_aux_sta_for_hs20: pointer to the function that adds an aux sta * @add_aux_sta_for_hs20: pointer to the function that adds an aux sta
* for Hot Spot 2.0 * for Hot Spot 2.0
* @switch_phy_ctxt: pointer to the function that switches a vif from one * @link: For a P2P Device interface, pointer to a function that links the
* phy_ctx to another * MAC/Link to the PHY context
*/ */
struct iwl_mvm_roc_ops { struct iwl_mvm_roc_ops {
int (*add_aux_sta_for_hs20)(struct iwl_mvm *mvm, u32 lmac_id); int (*add_aux_sta_for_hs20)(struct iwl_mvm *mvm, u32 lmac_id);
int (*switch_phy_ctxt)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int (*link)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
struct iwl_mvm_phy_ctxt *new_phy_ctxt);
}; };
int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
......
...@@ -78,9 +78,29 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) ...@@ -78,9 +78,29 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
*/ */
if (!WARN_ON(!mvm->p2p_device_vif)) { if (!WARN_ON(!mvm->p2p_device_vif)) {
mvmvif = iwl_mvm_vif_from_mac80211(mvm->p2p_device_vif); struct ieee80211_vif *vif = mvm->p2p_device_vif;
mvmvif = iwl_mvm_vif_from_mac80211(vif);
iwl_mvm_flush_sta(mvm, &mvmvif->deflink.bcast_sta, iwl_mvm_flush_sta(mvm, &mvmvif->deflink.bcast_sta,
true); true);
if (mvm->mld_api_is_used) {
iwl_mvm_mld_rm_bcast_sta(mvm, vif,
&vif->bss_conf);
iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
LINK_CONTEXT_MODIFY_ACTIVE,
false);
} else {
iwl_mvm_rm_p2p_bcast_sta(mvm, vif);
iwl_mvm_binding_remove_vif(mvm, vif);
}
/* Do not remove the PHY context as removing and adding
* a PHY context has timing overheads. Leaving it
* configured in FW would be useful in case the next ROC
* is with the same channel.
*/
} }
} }
...@@ -880,8 +900,8 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, ...@@ -880,8 +900,8 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) { if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) {
/* End TE, notify mac80211 */ /* End TE, notify mac80211 */
mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID; mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID;
ieee80211_remain_on_channel_expired(mvm->hw);
iwl_mvm_p2p_roc_finished(mvm); iwl_mvm_p2p_roc_finished(mvm);
ieee80211_remain_on_channel_expired(mvm->hw);
} else if (le32_to_cpu(notif->start)) { } else if (le32_to_cpu(notif->start)) {
if (WARN_ON(mvmvif->time_event_data.id != if (WARN_ON(mvmvif->time_event_data.id !=
le32_to_cpu(notif->conf_id))) le32_to_cpu(notif->conf_id)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment