wifi: iwlwifi: mvm: refactor iwl_mvm_add_sta(), iwl_mvm_rm_sta()
As we have a new MLD STA cmd, there will be a different function to add/remove a station in MLD mode. But both functions will share a common part. Put this part in a separate function which will be used later in adding/removing a sta in MLD mode. 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/20230320122330.d01e0c9ccdc3.I5e9e27c3b363b36209a0ff960d2e59708e7ff0bf@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
6a8dee1391
commit
69aef84805
1 changed files with 126 additions and 96 deletions
|
@ -1648,52 +1648,17 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
/* Initialize driver data of a new sta */
|
||||||
struct ieee80211_vif *vif,
|
static int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta)
|
struct ieee80211_sta *sta, int sta_id, u8 sta_type)
|
||||||
{
|
{
|
||||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||||
struct iwl_mvm_rxq_dup_data *dup_data;
|
struct iwl_mvm_rxq_dup_data *dup_data;
|
||||||
int i, ret, sta_id;
|
int i, ret = 0;
|
||||||
bool sta_update = false;
|
|
||||||
unsigned int sta_flags = 0;
|
|
||||||
|
|
||||||
lockdep_assert_held(&mvm->mutex);
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
|
||||||
sta_id = iwl_mvm_find_free_sta_id(mvm,
|
|
||||||
ieee80211_vif_type_p2p(vif));
|
|
||||||
else
|
|
||||||
sta_id = mvm_sta->sta_id;
|
|
||||||
|
|
||||||
if (sta_id == IWL_MVM_INVALID_STA)
|
|
||||||
return -ENOSPC;
|
|
||||||
|
|
||||||
spin_lock_init(&mvm_sta->lock);
|
|
||||||
|
|
||||||
/* if this is a HW restart re-alloc existing queues */
|
|
||||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
|
||||||
struct iwl_mvm_int_sta tmp_sta = {
|
|
||||||
.sta_id = sta_id,
|
|
||||||
.type = mvm_sta->sta_type,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First add an empty station since allocating
|
|
||||||
* a queue requires a valid station
|
|
||||||
*/
|
|
||||||
ret = iwl_mvm_add_int_sta_common(mvm, &tmp_sta, sta->addr,
|
|
||||||
mvmvif->id, mvmvif->color);
|
|
||||||
if (ret)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
iwl_mvm_realloc_queues_after_restart(mvm, sta);
|
|
||||||
sta_update = true;
|
|
||||||
sta_flags = iwl_mvm_has_new_tx_api(mvm) ? 0 : STA_MODIFY_QUEUES;
|
|
||||||
goto update_fw;
|
|
||||||
}
|
|
||||||
|
|
||||||
mvm_sta->sta_id = sta_id;
|
mvm_sta->sta_id = sta_id;
|
||||||
mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
|
mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||||
mvmvif->color);
|
mvmvif->color);
|
||||||
|
@ -1703,7 +1668,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||||
else
|
else
|
||||||
mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
|
mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
|
||||||
mvm_sta->tt_tx_protection = false;
|
mvm_sta->tt_tx_protection = false;
|
||||||
mvm_sta->sta_type = sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK;
|
mvm_sta->sta_type = sta_type;
|
||||||
|
|
||||||
mvm_sta->tid_disable_agg = 0xffff; /* No aggs at first */
|
mvm_sta->tid_disable_agg = 0xffff; /* No aggs at first */
|
||||||
|
|
||||||
|
@ -1724,8 +1689,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||||
atomic_set(&mvmtxq->tx_request, 0);
|
atomic_set(&mvmtxq->tx_request, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iwl_mvm_has_new_rx_api(mvm) &&
|
if (iwl_mvm_has_new_rx_api(mvm)) {
|
||||||
!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
|
||||||
int q;
|
int q;
|
||||||
|
|
||||||
dup_data = kcalloc(mvm->trans->num_rx_queues,
|
dup_data = kcalloc(mvm->trans->num_rx_queues,
|
||||||
|
@ -1751,7 +1715,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||||
ret = iwl_mvm_reserve_sta_stream(mvm, sta,
|
ret = iwl_mvm_reserve_sta_stream(mvm, sta,
|
||||||
ieee80211_vif_type_p2p(vif));
|
ieee80211_vif_type_p2p(vif));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1765,6 +1729,56 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||||
|
|
||||||
iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant);
|
iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta)
|
||||||
|
{
|
||||||
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
|
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||||
|
int ret, sta_id;
|
||||||
|
bool sta_update = false;
|
||||||
|
unsigned int sta_flags = 0;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
|
||||||
|
sta_id = iwl_mvm_find_free_sta_id(mvm,
|
||||||
|
ieee80211_vif_type_p2p(vif));
|
||||||
|
else
|
||||||
|
sta_id = mvm_sta->sta_id;
|
||||||
|
|
||||||
|
if (sta_id == IWL_MVM_INVALID_STA)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
|
spin_lock_init(&mvm_sta->lock);
|
||||||
|
|
||||||
|
/* if this is a HW restart re-alloc existing queues */
|
||||||
|
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
||||||
|
struct iwl_mvm_int_sta tmp_sta = {
|
||||||
|
.sta_id = sta_id,
|
||||||
|
.type = mvm_sta->sta_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* First add an empty station since allocating
|
||||||
|
* a queue requires a valid station
|
||||||
|
*/
|
||||||
|
ret = iwl_mvm_add_int_sta_common(mvm, &tmp_sta, sta->addr,
|
||||||
|
mvmvif->id, mvmvif->color);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
iwl_mvm_realloc_queues_after_restart(mvm, sta);
|
||||||
|
sta_update = true;
|
||||||
|
sta_flags = iwl_mvm_has_new_tx_api(mvm) ? 0 : STA_MODIFY_QUEUES;
|
||||||
|
goto update_fw;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = iwl_mvm_sta_init(mvm, vif, sta, sta_id,
|
||||||
|
sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK);
|
||||||
|
|
||||||
update_fw:
|
update_fw:
|
||||||
ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags);
|
ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1912,13 +1926,77 @@ int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
/* Execute the common part for both MLD and non-MLD modes */
|
||||||
struct ieee80211_vif *vif,
|
static bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta)
|
struct ieee80211_sta *sta, int *ret)
|
||||||
{
|
{
|
||||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||||
u8 sta_id = mvm_sta->sta_id;
|
u8 sta_id = mvm_sta->sta_id;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
/* If there is a TXQ still marked as reserved - free it */
|
||||||
|
if (mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) {
|
||||||
|
u8 reserved_txq = mvm_sta->reserved_queue;
|
||||||
|
enum iwl_mvm_queue_status *status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no traffic has gone through the reserved TXQ - it
|
||||||
|
* is still marked as IWL_MVM_QUEUE_RESERVED, and
|
||||||
|
* should be manually marked as free again
|
||||||
|
*/
|
||||||
|
status = &mvm->queue_info[reserved_txq].status;
|
||||||
|
if (WARN((*status != IWL_MVM_QUEUE_RESERVED) &&
|
||||||
|
(*status != IWL_MVM_QUEUE_FREE),
|
||||||
|
"sta_id %d reserved txq %d status %d",
|
||||||
|
sta_id, reserved_txq, *status)) {
|
||||||
|
*ret = -EINVAL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*status = IWL_MVM_QUEUE_FREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||||
|
mvmvif->ap_sta_id == sta_id) {
|
||||||
|
/* if associated - we can't remove the AP STA now */
|
||||||
|
if (vif->cfg.assoc)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* first remove remaining keys */
|
||||||
|
iwl_mvm_sec_key_remove_ap(mvm, vif);
|
||||||
|
|
||||||
|
/* unassoc - go ahead - remove the AP STA now */
|
||||||
|
mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This shouldn't happen - the TDLS channel switch should be canceled
|
||||||
|
* before the STA is removed.
|
||||||
|
*/
|
||||||
|
if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == sta_id)) {
|
||||||
|
mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
|
||||||
|
cancel_delayed_work(&mvm->tdls_cs.dwork);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure that the tx response code sees the station as -EBUSY and
|
||||||
|
* calls the drain worker.
|
||||||
|
*/
|
||||||
|
spin_lock_bh(&mvm_sta->lock);
|
||||||
|
spin_unlock_bh(&mvm_sta->lock);
|
||||||
|
|
||||||
|
iwl_mvm_time_sync_sta_rm(mvm, sta);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta)
|
||||||
|
{
|
||||||
|
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lockdep_assert_held(&mvm->mutex);
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
@ -1949,57 +2027,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||||
|
|
||||||
iwl_mvm_disable_sta_queues(mvm, vif, sta);
|
iwl_mvm_disable_sta_queues(mvm, vif, sta);
|
||||||
|
|
||||||
/* If there is a TXQ still marked as reserved - free it */
|
if (iwl_mvm_sta_del(mvm, vif, sta, &ret))
|
||||||
if (mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) {
|
|
||||||
u8 reserved_txq = mvm_sta->reserved_queue;
|
|
||||||
enum iwl_mvm_queue_status *status;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If no traffic has gone through the reserved TXQ - it
|
|
||||||
* is still marked as IWL_MVM_QUEUE_RESERVED, and
|
|
||||||
* should be manually marked as free again
|
|
||||||
*/
|
|
||||||
status = &mvm->queue_info[reserved_txq].status;
|
|
||||||
if (WARN((*status != IWL_MVM_QUEUE_RESERVED) &&
|
|
||||||
(*status != IWL_MVM_QUEUE_FREE),
|
|
||||||
"sta_id %d reserved txq %d status %d",
|
|
||||||
sta_id, reserved_txq, *status))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
*status = IWL_MVM_QUEUE_FREE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
|
||||||
mvmvif->ap_sta_id == sta_id) {
|
|
||||||
/* if associated - we can't remove the AP STA now */
|
|
||||||
if (vif->cfg.assoc)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* first remove remaining keys */
|
|
||||||
iwl_mvm_sec_key_remove_ap(mvm, vif);
|
|
||||||
|
|
||||||
/* unassoc - go ahead - remove the AP STA now */
|
|
||||||
mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This shouldn't happen - the TDLS channel switch should be canceled
|
|
||||||
* before the STA is removed.
|
|
||||||
*/
|
|
||||||
if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == sta_id)) {
|
|
||||||
mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
|
|
||||||
cancel_delayed_work(&mvm->tdls_cs.dwork);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure that the tx response code sees the station as -EBUSY and
|
|
||||||
* calls the drain worker.
|
|
||||||
*/
|
|
||||||
spin_lock_bh(&mvm_sta->lock);
|
|
||||||
spin_unlock_bh(&mvm_sta->lock);
|
|
||||||
|
|
||||||
iwl_mvm_time_sync_sta_rm(mvm, sta);
|
|
||||||
|
|
||||||
ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
|
ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
|
||||||
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
|
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue