From: Miri Korenblit <miriam.rachel.korenblit@xxxxxxxxx> 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@xxxxxxxxx> Signed-off-by: Gregory Greenman <gregory.greenman@xxxxxxxxx> --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 182 +++++++++++-------- 1 file changed, 106 insertions(+), 76 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index c22ba1ea42f6..7d9d4e85b548 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1648,52 +1648,17 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, return ret; } -int iwl_mvm_add_sta(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +/* Initialize driver data of a new sta */ +static int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, int sta_id, u8 sta_type) { 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_rxq_dup_data *dup_data; - int i, ret, sta_id; - bool sta_update = false; - unsigned int sta_flags = 0; + int i, ret = 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; - } - mvm_sta->sta_id = sta_id; mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); @@ -1703,7 +1668,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, else mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF; 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 */ @@ -1724,8 +1689,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, atomic_set(&mvmtxq->tx_request, 0); } - if (iwl_mvm_has_new_rx_api(mvm) && - !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { + if (iwl_mvm_has_new_rx_api(mvm)) { int q; 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, ieee80211_vif_type_p2p(vif)); 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); + 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: ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags); if (ret) @@ -1912,43 +1926,16 @@ int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm, return 0; } -int iwl_mvm_rm_sta(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +/* Execute the common part for both MLD and non-MLD modes */ +static bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, int *ret) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); u8 sta_id = mvm_sta->sta_id; - int ret; lockdep_assert_held(&mvm->mutex); - if (iwl_mvm_has_new_rx_api(mvm)) - kfree(mvm_sta->dup_data); - - ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); - if (ret) - return ret; - - /* flush its queues here since we are freeing mvm_sta */ - ret = iwl_mvm_flush_sta(mvm, mvm_sta, false); - if (ret) - return ret; - if (iwl_mvm_has_new_tx_api(mvm)) { - ret = iwl_mvm_wait_sta_queues_empty(mvm, mvm_sta); - } else { - u32 q_mask = mvm_sta->tfd_queue_msk; - - ret = iwl_trans_wait_tx_queues_empty(mvm->trans, - q_mask); - } - if (ret) - return ret; - - ret = iwl_mvm_drain_sta(mvm, mvm_sta, false); - - iwl_mvm_disable_sta_queues(mvm, vif, sta); - /* 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; @@ -1963,8 +1950,10 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, 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; + sta_id, reserved_txq, *status)) { + *ret = -EINVAL; + return true; + } *status = IWL_MVM_QUEUE_FREE; } @@ -1973,7 +1962,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, mvmvif->ap_sta_id == sta_id) { /* if associated - we can't remove the AP STA now */ if (vif->cfg.assoc) - return ret; + return true; /* first remove remaining keys */ iwl_mvm_sec_key_remove_ap(mvm, vif); @@ -2000,6 +1989,47 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, 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; + + lockdep_assert_held(&mvm->mutex); + + if (iwl_mvm_has_new_rx_api(mvm)) + kfree(mvm_sta->dup_data); + + ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); + if (ret) + return ret; + + /* flush its queues here since we are freeing mvm_sta */ + ret = iwl_mvm_flush_sta(mvm, mvm_sta, false); + if (ret) + return ret; + if (iwl_mvm_has_new_tx_api(mvm)) { + ret = iwl_mvm_wait_sta_queues_empty(mvm, mvm_sta); + } else { + u32 q_mask = mvm_sta->tfd_queue_msk; + + ret = iwl_trans_wait_tx_queues_empty(mvm->trans, + q_mask); + } + if (ret) + return ret; + + ret = iwl_mvm_drain_sta(mvm, mvm_sta, false); + + iwl_mvm_disable_sta_queues(mvm, vif, sta); + + if (iwl_mvm_sta_del(mvm, vif, sta, &ret)) + return ret; + 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); -- 2.38.1