diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/sta.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 173 |
1 files changed, 53 insertions, 120 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index cd74c181c260..11c6b86db4ec 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2015, 2018-2024 Intel Corporation + * Copyright (C) 2012-2015, 2018-2025 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -253,7 +253,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, static void iwl_mvm_rx_agg_session_expired(struct timer_list *t) { struct iwl_mvm_baid_data *data = - from_timer(data, t, session_timer); + timer_container_of(data, t, session_timer); struct iwl_mvm_baid_data __rcu **rcu_ptr = data->rcu_ptr; struct iwl_mvm_baid_data *ba_data; struct ieee80211_sta *sta; @@ -791,10 +791,10 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, lockdep_assert_held(&mvm->mutex); - if (WARN(maxq >= mvm->trans->trans_cfg->base_params->num_of_queues, + if (WARN(maxq >= mvm->trans->mac_cfg->base->num_of_queues, "max queue %d >= num_of_queues (%d)", maxq, - mvm->trans->trans_cfg->base_params->num_of_queues)) - maxq = mvm->trans->trans_cfg->base_params->num_of_queues - 1; + mvm->trans->mac_cfg->base->num_of_queues)) + maxq = mvm->trans->mac_cfg->base->num_of_queues - 1; /* This should not be hit with new TX path */ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) @@ -852,7 +852,7 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, if (tid == IWL_MAX_TID_COUNT) { tid = IWL_MGMT_TID; size = max_t(u32, IWL_MGMT_QUEUE_SIZE, - mvm->trans->cfg->min_txq_size); + mvm->trans->mac_cfg->base->min_txq_size); } else { size = iwl_mvm_get_queue_size(sta); } @@ -1520,7 +1520,12 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, add_stream_wk); - mutex_lock(&mvm->mutex); + guard(mvm)(mvm); + + /* will reschedule to run after restart */ + if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) || + test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) + return; iwl_mvm_inactivity_check(mvm, IWL_INVALID_STA); @@ -1564,8 +1569,6 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) iwl_mvm_mac_itxq_xmit(mvm->hw, txq); local_bh_enable(); } - - mutex_unlock(&mvm->mutex); } static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm, @@ -1762,7 +1765,7 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvm_sta->deflink.sta_id = sta_id; rcu_assign_pointer(mvm_sta->link[0], &mvm_sta->deflink); - if (!mvm->trans->trans_cfg->gen2) + if (!mvm->trans->mac_cfg->gen2) mvm_sta->deflink.lq_sta.rs_drv.pers.max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF; else @@ -1795,7 +1798,7 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (iwl_mvm_has_new_rx_api(mvm)) { int q; - dup_data = kcalloc(mvm->trans->num_rx_queues, + dup_data = kcalloc(mvm->trans->info.num_rxqs, sizeof(*dup_data), GFP_KERNEL); if (!dup_data) return -ENOMEM; @@ -1808,7 +1811,7 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif, * This thus allows receiving a packet with seqno 0 and the * retry bit set as the very first packet on a new TID. */ - for (q = 0; q < mvm->trans->num_rx_queues; q++) + for (q = 0; q < mvm->trans->info.num_rxqs; q++) memset(dup_data[q].last_seq, 0xff, sizeof(dup_data[q].last_seq)); mvm_sta->dup_data = dup_data; @@ -1836,11 +1839,11 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && !sta->tdls && ieee80211_vif_is_mld(vif)) { mvm_sta->mpdu_counters = - kcalloc(mvm->trans->num_rx_queues, + kcalloc(mvm->trans->info.num_rxqs, sizeof(*mvm_sta->mpdu_counters), GFP_KERNEL); if (mvm_sta->mpdu_counters) - for (int q = 0; q < mvm->trans->num_rx_queues; q++) + for (int q = 0; q < mvm->trans->info.num_rxqs; q++) spin_lock_init(&mvm_sta->mpdu_counters[q].lock); } @@ -2045,9 +2048,9 @@ int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm, * Returns if we're done with removing the station, either * with error or success */ -bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, +void iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_link_sta *link_sta, int *ret) + struct ieee80211_link_sta *link_sta) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif_link_info *mvm_link = @@ -2063,38 +2066,12 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, lockdep_is_held(&mvm->mutex)); sta_id = mvm_link_sta->sta_id; - /* 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 && mvm_link->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, mvm_link, 0); + iwl_mvm_sec_key_remove_ap(mvm, vif, mvm_link, + link_sta->link_id); - /* unassoc - go ahead - remove the AP STA now */ mvm_link->ap_sta_id = IWL_INVALID_STA; } @@ -2106,8 +2083,6 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA; cancel_delayed_work(&mvm->tdls_cs.dwork); } - - return false; } int iwl_mvm_rm_sta(struct iwl_mvm *mvm, @@ -2143,8 +2118,27 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, iwl_mvm_disable_sta_queues(mvm, vif, sta); - if (iwl_mvm_sta_del(mvm, vif, sta, &sta->deflink, &ret)) - return ret; + /* 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", + mvm_sta->deflink.sta_id, reserved_txq, *status)) + return -EINVAL; + + *status = IWL_MVM_QUEUE_FREE; + } + + iwl_mvm_sta_del(mvm, vif, sta, &sta->deflink); ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->deflink.sta_id); RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->deflink.sta_id], NULL); @@ -2195,7 +2189,7 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue, u8 sta_id, u8 fifo) { unsigned int wdg_timeout = - mvm->trans->trans_cfg->base_params->wd_timeout; + mvm->trans->mac_cfg->base->wd_timeout; struct iwl_trans_txq_scd_cfg cfg = { .fifo = fifo, .sta_id = sta_id, @@ -2212,7 +2206,7 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue, static int iwl_mvm_enable_aux_snif_queue_tvqm(struct iwl_mvm *mvm, u8 sta_id) { unsigned int wdg_timeout = - mvm->trans->trans_cfg->base_params->wd_timeout; + mvm->trans->mac_cfg->base->wd_timeout; WARN_ON(!iwl_mvm_has_new_tx_api(mvm)); @@ -2467,7 +2461,7 @@ void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm, mvmvif->deflink.bcast_sta.tfd_queue_msk &= ~BIT(queue); } -/* Send the FW a request to remove the station from it's internal data +/* Send the FW a request to remove the station from its internal data * structures, but DO NOT remove the entry from the local data structures. */ int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -2530,7 +2524,7 @@ void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) } /* - * Send the FW a request to remove the station from it's internal data + * Send the FW a request to remove the station from its internal data * structures, and in addition remove it from the local data structure. */ int iwl_mvm_rm_p2p_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) @@ -2683,7 +2677,7 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, } /* - * Send the FW a request to remove the station from it's internal data + * Send the FW a request to remove the station from its internal data * structures, and in addition remove it from the local data structure. */ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) @@ -2723,7 +2717,7 @@ static void iwl_mvm_free_reorder(struct iwl_mvm *mvm, iwl_mvm_sync_rxq_del_ba(mvm, data->baid); - for (i = 0; i < mvm->trans->num_rx_queues; i++) { + for (i = 0; i < mvm->trans->info.num_rxqs; i++) { int j; struct iwl_mvm_reorder_buffer *reorder_buf = &data->reorder_buf[i]; @@ -2756,7 +2750,7 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm, { int i; - for (i = 0; i < mvm->trans->num_rx_queues; i++) { + for (i = 0; i < mvm->trans->info.num_rxqs; i++) { struct iwl_mvm_reorder_buffer *reorder_buf = &data->reorder_buf[i]; struct iwl_mvm_reorder_buf_entry *entries = @@ -2912,7 +2906,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, /* * The division below will be OK if either the cache line size * can be divided by the entry size (ALIGN will round up) or if - * if the entry size can be divided by the cache line size, in + * the entry size can be divided by the cache line size, in * which case the ALIGN() will do nothing. */ BUILD_BUG_ON(SMP_CACHE_BYTES % sizeof(baid_data->entries[0]) && @@ -2931,7 +2925,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, * before starting the BA session in the firmware */ baid_data = kzalloc(sizeof(*baid_data) + - mvm->trans->num_rx_queues * + mvm->trans->info.num_rxqs * reorder_buf_size, GFP_KERNEL); if (!baid_data) @@ -3183,7 +3177,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, * to align the wrap around of ssn so we compare relevant values. */ normalized_ssn = tid_data->ssn; - if (mvm->trans->trans_cfg->gen2) + if (mvm->trans->mac_cfg->gen2) normalized_ssn &= 0xff; if (normalized_ssn == tid_data->next_reclaimed) { @@ -4311,73 +4305,12 @@ u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data) * In 22000 HW, the next_reclaimed index is only 8 bit, so we'll need * to align the wrap around of ssn so we compare relevant values. */ - if (mvm->trans->trans_cfg->gen2) + if (mvm->trans->mac_cfg->gen2) sn &= 0xff; return ieee80211_sn_sub(sn, tid_data->next_reclaimed); } -int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct iwl_mvm_int_sta *sta, u8 *addr, u32 cipher, - u8 *key, u32 key_len, - struct ieee80211_key_conf *keyconf) -{ - int ret; - u16 queue; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - unsigned int wdg_timeout = - iwl_mvm_get_wd_timeout(mvm, vif); - bool mld = iwl_mvm_has_mld_api(mvm->fw); - u32 type = IWL_STA_LINK; - - if (mld) - type = STATION_TYPE_PEER; - - ret = iwl_mvm_allocate_int_sta(mvm, sta, 0, - NL80211_IFTYPE_UNSPECIFIED, type); - if (ret) - return ret; - - if (mld) - ret = iwl_mvm_mld_add_int_sta_with_queue(mvm, sta, addr, - mvmvif->deflink.fw_link_id, - &queue, - IWL_MAX_TID_COUNT, - &wdg_timeout); - else - ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, - mvmvif->color, addr, sta, - &queue, - IWL_MVM_TX_FIFO_BE); - if (ret) - goto out; - - keyconf->cipher = cipher; - memcpy(keyconf->key, key, key_len); - keyconf->keylen = key_len; - keyconf->flags = IEEE80211_KEY_FLAG_PAIRWISE; - - if (mld) { - /* The MFP flag is set according to the station mfp field. Since - * we don't have a station, set it manually. - */ - u32 key_flags = - iwl_mvm_get_sec_flags(mvm, vif, NULL, keyconf) | - IWL_SEC_KEY_FLAG_MFP; - u32 sta_mask = BIT(sta->sta_id); - - ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf); - } else { - ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false, - 0, NULL, 0, 0, true); - } - -out: - if (ret) - iwl_mvm_dealloc_int_sta(mvm, sta); - return ret; -} - void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u32 id) |