|
@@ -7,7 +7,7 @@
|
|
|
*
|
|
|
* Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
|
|
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
|
|
- * Copyright(c) 2016 Intel Deutschland GmbH
|
|
|
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
* it under the terms of version 2 of the GNU General Public License as
|
|
@@ -34,7 +34,7 @@
|
|
|
*
|
|
|
* Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
|
|
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
|
|
- * Copyright(c) 2016 Intel Deutschland GmbH
|
|
|
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
|
|
* All rights reserved.
|
|
|
*
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -98,7 +98,7 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
|
|
|
reserved_ids = BIT(0);
|
|
|
|
|
|
/* Don't take rcu_read_lock() since we are protected by mvm->mutex */
|
|
|
- for (sta_id = 0; sta_id < IWL_MVM_STATION_COUNT; sta_id++) {
|
|
|
+ for (sta_id = 0; sta_id < ARRAY_SIZE(mvm->fw_id_to_mac_id); sta_id++) {
|
|
|
if (BIT(sta_id) & reserved_ids)
|
|
|
continue;
|
|
|
|
|
@@ -106,7 +106,7 @@ static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
|
|
|
lockdep_is_held(&mvm->mutex)))
|
|
|
return sta_id;
|
|
|
}
|
|
|
- return IWL_MVM_STATION_COUNT;
|
|
|
+ return IWL_MVM_INVALID_STA;
|
|
|
}
|
|
|
|
|
|
/* send station add/update command to firmware */
|
|
@@ -127,11 +127,17 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
|
u32 agg_size = 0, mpdu_dens = 0;
|
|
|
|
|
|
if (!update || (flags & STA_MODIFY_QUEUES)) {
|
|
|
- add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
|
|
|
memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
|
|
|
|
|
|
- if (flags & STA_MODIFY_QUEUES)
|
|
|
- add_sta_cmd.modify_mask |= STA_MODIFY_QUEUES;
|
|
|
+ if (!iwl_mvm_has_new_tx_api(mvm)) {
|
|
|
+ add_sta_cmd.tfd_queue_msk =
|
|
|
+ cpu_to_le32(mvm_sta->tfd_queue_msk);
|
|
|
+
|
|
|
+ if (flags & STA_MODIFY_QUEUES)
|
|
|
+ add_sta_cmd.modify_mask |= STA_MODIFY_QUEUES;
|
|
|
+ } else {
|
|
|
+ WARN_ON(flags & STA_MODIFY_QUEUES);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
switch (sta->bandwidth) {
|
|
@@ -209,13 +215,15 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
|
add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS;
|
|
|
|
|
|
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
|
|
|
- add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BK);
|
|
|
+ add_sta_cmd.uapsd_acs |= BIT(AC_BK);
|
|
|
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
|
|
|
- add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BE);
|
|
|
+ add_sta_cmd.uapsd_acs |= BIT(AC_BE);
|
|
|
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
|
|
|
- add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VI);
|
|
|
+ add_sta_cmd.uapsd_acs |= BIT(AC_VI);
|
|
|
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
|
|
|
- add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VO);
|
|
|
+ add_sta_cmd.uapsd_acs |= BIT(AC_VO);
|
|
|
+ add_sta_cmd.uapsd_acs |= add_sta_cmd.uapsd_acs << 4;
|
|
|
+ add_sta_cmd.sp_length = sta->max_sp ? sta->max_sp * 2 : 128;
|
|
|
}
|
|
|
|
|
|
status = ADD_STA_SUCCESS;
|
|
@@ -337,6 +345,9 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue,
|
|
|
u8 sta_id;
|
|
|
int ret;
|
|
|
|
|
|
+ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
spin_lock_bh(&mvm->queue_info_lock);
|
|
|
sta_id = mvm->queue_info[queue].ra_sta_id;
|
|
|
spin_unlock_bh(&mvm->queue_info_lock);
|
|
@@ -387,6 +398,9 @@ static int iwl_mvm_get_queue_agg_tids(struct iwl_mvm *mvm, int queue)
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
+ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
spin_lock_bh(&mvm->queue_info_lock);
|
|
|
sta_id = mvm->queue_info[queue].ra_sta_id;
|
|
|
tid_bitmap = mvm->queue_info[queue].tid_bitmap;
|
|
@@ -426,6 +440,9 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
+ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
spin_lock_bh(&mvm->queue_info_lock);
|
|
|
sta_id = mvm->queue_info[queue].ra_sta_id;
|
|
|
tid_bitmap = mvm->queue_info[queue].tid_bitmap;
|
|
@@ -468,6 +485,9 @@ static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue,
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
+ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
spin_lock_bh(&mvm->queue_info_lock);
|
|
|
txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
|
|
|
sta_id = mvm->queue_info[queue].ra_sta_id;
|
|
@@ -512,6 +532,8 @@ static int iwl_mvm_get_shared_queue(struct iwl_mvm *mvm,
|
|
|
int i;
|
|
|
|
|
|
lockdep_assert_held(&mvm->queue_info_lock);
|
|
|
+ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
memset(&ac_to_queue, IEEE80211_INVAL_HW_QUEUE, sizeof(ac_to_queue));
|
|
|
|
|
@@ -596,6 +618,9 @@ int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid,
|
|
|
unsigned long mq;
|
|
|
int ret;
|
|
|
|
|
|
+ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
/*
|
|
|
* If the AC is lower than current one - FIFO needs to be redirected to
|
|
|
* the lowest one of the streams in the queue. Check if this is needed
|
|
@@ -677,6 +702,41 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm,
|
|
|
+ struct ieee80211_sta *sta, u8 ac,
|
|
|
+ int tid)
|
|
|
+{
|
|
|
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
|
|
+ unsigned int wdg_timeout =
|
|
|
+ iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false);
|
|
|
+ u8 mac_queue = mvmsta->vif->hw_queue[ac];
|
|
|
+ int queue = -1;
|
|
|
+
|
|
|
+ lockdep_assert_held(&mvm->mutex);
|
|
|
+
|
|
|
+ IWL_DEBUG_TX_QUEUES(mvm,
|
|
|
+ "Allocating queue for sta %d on tid %d\n",
|
|
|
+ mvmsta->sta_id, tid);
|
|
|
+ queue = iwl_mvm_tvqm_enable_txq(mvm, mac_queue, mvmsta->sta_id, tid,
|
|
|
+ wdg_timeout);
|
|
|
+ if (queue < 0)
|
|
|
+ return queue;
|
|
|
+
|
|
|
+ IWL_DEBUG_TX_QUEUES(mvm, "Allocated queue is %d\n", queue);
|
|
|
+
|
|
|
+ spin_lock_bh(&mvmsta->lock);
|
|
|
+ mvmsta->tid_data[tid].txq_id = queue;
|
|
|
+ mvmsta->tid_data[tid].is_tid_active = true;
|
|
|
+ mvmsta->tfd_queue_msk |= BIT(queue);
|
|
|
+ spin_unlock_bh(&mvmsta->lock);
|
|
|
+
|
|
|
+ spin_lock_bh(&mvm->queue_info_lock);
|
|
|
+ mvm->queue_info[queue].status = IWL_MVM_QUEUE_READY;
|
|
|
+ spin_unlock_bh(&mvm->queue_info_lock);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
|
|
struct ieee80211_sta *sta, u8 ac, int tid,
|
|
|
struct ieee80211_hdr *hdr)
|
|
@@ -702,6 +762,9 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
+ if (iwl_mvm_has_new_tx_api(mvm))
|
|
|
+ return iwl_mvm_sta_alloc_queue_tvqm(mvm, sta, ac, tid);
|
|
|
+
|
|
|
spin_lock_bh(&mvmsta->lock);
|
|
|
tfd_queue_mask = mvmsta->tfd_queue_msk;
|
|
|
spin_unlock_bh(&mvmsta->lock);
|
|
@@ -880,6 +943,9 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue)
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
+ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
|
|
|
+ return;
|
|
|
+
|
|
|
spin_lock_bh(&mvm->queue_info_lock);
|
|
|
tid_bitmap = mvm->queue_info[queue].tid_bitmap;
|
|
|
spin_unlock_bh(&mvm->queue_info_lock);
|
|
@@ -917,6 +983,10 @@ static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)
|
|
|
int ssn;
|
|
|
int ret = true;
|
|
|
|
|
|
+ /* queue sharing is disabled on new TX path */
|
|
|
+ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
|
|
|
+ return;
|
|
|
+
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
spin_lock_bh(&mvm->queue_info_lock);
|
|
@@ -1199,18 +1269,30 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
|
|
|
ac = tid_to_mac80211_ac[i];
|
|
|
mac_queue = mvm_sta->vif->hw_queue[ac];
|
|
|
|
|
|
- cfg.tid = i;
|
|
|
- cfg.fifo = iwl_mvm_ac_to_tx_fifo[ac];
|
|
|
- cfg.aggregate = (txq_id >= IWL_MVM_DQA_MIN_DATA_QUEUE ||
|
|
|
- txq_id == IWL_MVM_DQA_BSS_CLIENT_QUEUE);
|
|
|
+ if (iwl_mvm_has_new_tx_api(mvm)) {
|
|
|
+ IWL_DEBUG_TX_QUEUES(mvm,
|
|
|
+ "Re-mapping sta %d tid %d\n",
|
|
|
+ mvm_sta->sta_id, i);
|
|
|
+ txq_id = iwl_mvm_tvqm_enable_txq(mvm, mac_queue,
|
|
|
+ mvm_sta->sta_id,
|
|
|
+ i, wdg_timeout);
|
|
|
+ tid_data->txq_id = txq_id;
|
|
|
+ } else {
|
|
|
+ u16 seq = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
|
|
|
+
|
|
|
+ cfg.tid = i;
|
|
|
+ cfg.fifo = iwl_mvm_ac_to_tx_fifo[ac];
|
|
|
+ cfg.aggregate = (txq_id >= IWL_MVM_DQA_MIN_DATA_QUEUE ||
|
|
|
+ txq_id ==
|
|
|
+ IWL_MVM_DQA_BSS_CLIENT_QUEUE);
|
|
|
|
|
|
- IWL_DEBUG_TX_QUEUES(mvm,
|
|
|
- "Re-mapping sta %d tid %d to queue %d\n",
|
|
|
- mvm_sta->sta_id, i, txq_id);
|
|
|
+ IWL_DEBUG_TX_QUEUES(mvm,
|
|
|
+ "Re-mapping sta %d tid %d to queue %d\n",
|
|
|
+ mvm_sta->sta_id, i, txq_id);
|
|
|
|
|
|
- iwl_mvm_enable_txq(mvm, txq_id, mac_queue,
|
|
|
- IEEE80211_SEQ_TO_SN(tid_data->seq_number),
|
|
|
- &cfg, wdg_timeout);
|
|
|
+ iwl_mvm_enable_txq(mvm, txq_id, mac_queue, seq, &cfg,
|
|
|
+ wdg_timeout);
|
|
|
+ }
|
|
|
|
|
|
mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_READY;
|
|
|
}
|
|
@@ -1235,7 +1317,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
|
|
else
|
|
|
sta_id = mvm_sta->sta_id;
|
|
|
|
|
|
- if (sta_id == IWL_MVM_STATION_COUNT)
|
|
|
+ if (sta_id == IWL_MVM_INVALID_STA)
|
|
|
return -ENOSPC;
|
|
|
|
|
|
spin_lock_init(&mvm_sta->lock);
|
|
@@ -1317,10 +1399,10 @@ update_fw:
|
|
|
|
|
|
if (vif->type == NL80211_IFTYPE_STATION) {
|
|
|
if (!sta->tdls) {
|
|
|
- WARN_ON(mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT);
|
|
|
+ WARN_ON(mvmvif->ap_sta_id != IWL_MVM_INVALID_STA);
|
|
|
mvmvif->ap_sta_id = sta_id;
|
|
|
} else {
|
|
|
- WARN_ON(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT);
|
|
|
+ WARN_ON(mvmvif->ap_sta_id == IWL_MVM_INVALID_STA);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1571,11 +1653,11 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
|
|
return ret;
|
|
|
|
|
|
/* unassoc - go ahead - remove the AP STA now */
|
|
|
- mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
|
|
|
+ mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
|
|
|
|
|
|
/* clear d0i3_ap_sta_id if no longer relevant */
|
|
|
if (mvm->d0i3_ap_sta_id == sta_id)
|
|
|
- mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
|
|
|
+ mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1584,7 +1666,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
|
|
* 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_STATION_COUNT;
|
|
|
+ mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
|
|
|
cancel_delayed_work(&mvm->tdls_cs.dwork);
|
|
|
}
|
|
|
|
|
@@ -1641,7 +1723,7 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
|
|
|
{
|
|
|
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
|
|
sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype);
|
|
|
- if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_STATION_COUNT))
|
|
|
+ if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA))
|
|
|
return -ENOSPC;
|
|
|
}
|
|
|
|
|
@@ -1652,12 +1734,11 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm,
|
|
|
- struct iwl_mvm_int_sta *sta)
|
|
|
+void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta)
|
|
|
{
|
|
|
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta->sta_id], NULL);
|
|
|
memset(sta, 0, sizeof(struct iwl_mvm_int_sta));
|
|
|
- sta->sta_id = IWL_MVM_STATION_COUNT;
|
|
|
+ sta->sta_id = IWL_MVM_INVALID_STA;
|
|
|
}
|
|
|
|
|
|
static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
|
|
@@ -1676,7 +1757,8 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
|
|
|
cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id,
|
|
|
color));
|
|
|
|
|
|
- cmd.tfd_queue_msk = cpu_to_le32(sta->tfd_queue_msk);
|
|
|
+ if (!iwl_mvm_has_new_tx_api(mvm))
|
|
|
+ cmd.tfd_queue_msk = cpu_to_le32(sta->tfd_queue_msk);
|
|
|
cmd.tid_disable_tx = cpu_to_le16(0xffff);
|
|
|
|
|
|
if (addr)
|
|
@@ -1701,27 +1783,19 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
|
|
|
+static void iwl_mvm_enable_aux_queue(struct iwl_mvm *mvm)
|
|
|
{
|
|
|
unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
|
|
|
mvm->cfg->base_params->wd_timeout :
|
|
|
IWL_WATCHDOG_DISABLED;
|
|
|
- int ret;
|
|
|
-
|
|
|
- lockdep_assert_held(&mvm->mutex);
|
|
|
-
|
|
|
- /* Map Aux queue to fifo - needs to happen before adding Aux station */
|
|
|
- if (!iwl_mvm_is_dqa_supported(mvm))
|
|
|
- iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, mvm->aux_queue,
|
|
|
- IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
|
|
|
-
|
|
|
- /* Allocate aux station and assign to it the aux queue */
|
|
|
- ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
|
|
|
- NL80211_IFTYPE_UNSPECIFIED);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
|
|
|
- if (iwl_mvm_is_dqa_supported(mvm)) {
|
|
|
+ if (iwl_mvm_has_new_tx_api(mvm)) {
|
|
|
+ int queue = iwl_mvm_tvqm_enable_txq(mvm, mvm->aux_queue,
|
|
|
+ mvm->aux_sta.sta_id,
|
|
|
+ IWL_MAX_TID_COUNT,
|
|
|
+ wdg_timeout);
|
|
|
+ mvm->aux_queue = queue;
|
|
|
+ } else if (iwl_mvm_is_dqa_supported(mvm)) {
|
|
|
struct iwl_trans_txq_scd_cfg cfg = {
|
|
|
.fifo = IWL_MVM_TX_FIFO_MCAST,
|
|
|
.sta_id = mvm->aux_sta.sta_id,
|
|
@@ -1732,14 +1806,43 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
|
|
|
|
|
|
iwl_mvm_enable_txq(mvm, mvm->aux_queue, mvm->aux_queue, 0, &cfg,
|
|
|
wdg_timeout);
|
|
|
+ } else {
|
|
|
+ iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, mvm->aux_queue,
|
|
|
+ IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- ret = iwl_mvm_add_int_sta_common(mvm, &mvm->aux_sta, NULL,
|
|
|
- MAC_INDEX_AUX, 0);
|
|
|
+int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
+ /* Allocate aux station and assign to it the aux queue */
|
|
|
+ ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
|
|
|
+ NL80211_IFTYPE_UNSPECIFIED);
|
|
|
if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ /* Map Aux queue to fifo - needs to happen before adding Aux station */
|
|
|
+ if (!iwl_mvm_has_new_tx_api(mvm))
|
|
|
+ iwl_mvm_enable_aux_queue(mvm);
|
|
|
+
|
|
|
+ ret = iwl_mvm_add_int_sta_common(mvm, &mvm->aux_sta, NULL,
|
|
|
+ MAC_INDEX_AUX, 0);
|
|
|
+ if (ret) {
|
|
|
iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
|
|
|
- return ret;
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * For a000 firmware and on we cannot add queue to a station unknown
|
|
|
+ * to firmware so enable queue here - after the station was added
|
|
|
+ */
|
|
|
+ if (iwl_mvm_has_new_tx_api(mvm))
|
|
|
+ iwl_mvm_enable_aux_queue(mvm);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|
@@ -1790,39 +1893,39 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|
|
struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta;
|
|
|
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
|
|
const u8 *baddr = _baddr;
|
|
|
+ int queue = 0;
|
|
|
int ret;
|
|
|
+ unsigned int wdg_timeout =
|
|
|
+ iwl_mvm_get_wd_timeout(mvm, vif, false, false);
|
|
|
+ struct iwl_trans_txq_scd_cfg cfg = {
|
|
|
+ .fifo = IWL_MVM_TX_FIFO_VO,
|
|
|
+ .sta_id = mvmvif->bcast_sta.sta_id,
|
|
|
+ .tid = IWL_MAX_TID_COUNT,
|
|
|
+ .aggregate = false,
|
|
|
+ .frame_limit = IWL_FRAME_LIMIT,
|
|
|
+ };
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
- if (iwl_mvm_is_dqa_supported(mvm)) {
|
|
|
- struct iwl_trans_txq_scd_cfg cfg = {
|
|
|
- .fifo = IWL_MVM_TX_FIFO_VO,
|
|
|
- .sta_id = mvmvif->bcast_sta.sta_id,
|
|
|
- .tid = IWL_MAX_TID_COUNT,
|
|
|
- .aggregate = false,
|
|
|
- .frame_limit = IWL_FRAME_LIMIT,
|
|
|
- };
|
|
|
- unsigned int wdg_timeout =
|
|
|
- iwl_mvm_get_wd_timeout(mvm, vif, false, false);
|
|
|
- int queue;
|
|
|
-
|
|
|
+ if (iwl_mvm_is_dqa_supported(mvm) && !iwl_mvm_has_new_tx_api(mvm)) {
|
|
|
if (vif->type == NL80211_IFTYPE_AP ||
|
|
|
vif->type == NL80211_IFTYPE_ADHOC)
|
|
|
- queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
|
|
+ queue = mvm->probe_queue;
|
|
|
else if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
|
|
- queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE;
|
|
|
+ queue = mvm->p2p_dev_queue;
|
|
|
else if (WARN(1, "Missing required TXQ for adding bcast STA\n"))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- iwl_mvm_enable_txq(mvm, queue, vif->hw_queue[0], 0, &cfg,
|
|
|
- wdg_timeout);
|
|
|
bsta->tfd_queue_msk |= BIT(queue);
|
|
|
+
|
|
|
+ iwl_mvm_enable_txq(mvm, queue, vif->hw_queue[0], 0,
|
|
|
+ &cfg, wdg_timeout);
|
|
|
}
|
|
|
|
|
|
if (vif->type == NL80211_IFTYPE_ADHOC)
|
|
|
baddr = vif->bss_conf.bssid;
|
|
|
|
|
|
- if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_STATION_COUNT))
|
|
|
+ if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_INVALID_STA))
|
|
|
return -ENOSPC;
|
|
|
|
|
|
ret = iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
|
|
@@ -1831,27 +1934,20 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|
|
return ret;
|
|
|
|
|
|
/*
|
|
|
- * In AP vif type, we also need to enable the cab_queue. However, we
|
|
|
- * have to enable it after the ADD_STA command is sent, otherwise the
|
|
|
- * FW will throw an assert once we send the ADD_STA command (it'll
|
|
|
- * detect a mismatch in the tfd_queue_msk, as we can't add the
|
|
|
- * enabled-cab_queue to the mask)
|
|
|
+ * For a000 firmware and on we cannot add queue to a station unknown
|
|
|
+ * to firmware so enable queue here - after the station was added
|
|
|
*/
|
|
|
- if (iwl_mvm_is_dqa_supported(mvm) &&
|
|
|
- (vif->type == NL80211_IFTYPE_AP ||
|
|
|
- vif->type == NL80211_IFTYPE_ADHOC)) {
|
|
|
- struct iwl_trans_txq_scd_cfg cfg = {
|
|
|
- .fifo = IWL_MVM_TX_FIFO_MCAST,
|
|
|
- .sta_id = mvmvif->bcast_sta.sta_id,
|
|
|
- .tid = IWL_MAX_TID_COUNT,
|
|
|
- .aggregate = false,
|
|
|
- .frame_limit = IWL_FRAME_LIMIT,
|
|
|
- };
|
|
|
- unsigned int wdg_timeout =
|
|
|
- iwl_mvm_get_wd_timeout(mvm, vif, false, false);
|
|
|
+ if (iwl_mvm_has_new_tx_api(mvm)) {
|
|
|
+ int queue = iwl_mvm_tvqm_enable_txq(mvm, vif->hw_queue[0],
|
|
|
+ bsta->sta_id,
|
|
|
+ IWL_MAX_TID_COUNT,
|
|
|
+ wdg_timeout);
|
|
|
+ if (vif->type == NL80211_IFTYPE_AP)
|
|
|
+ mvm->probe_queue = queue;
|
|
|
+ else if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
|
|
+ mvm->p2p_dev_queue = queue;
|
|
|
|
|
|
- iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue,
|
|
|
- 0, &cfg, wdg_timeout);
|
|
|
+ bsta->tfd_queue_msk |= BIT(queue);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -1869,24 +1965,18 @@ static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
|
|
|
iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
|
|
|
IWL_MAX_TID_COUNT, 0);
|
|
|
|
|
|
- if (mvmvif->bcast_sta.tfd_queue_msk &
|
|
|
- BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE)) {
|
|
|
- iwl_mvm_disable_txq(mvm,
|
|
|
- IWL_MVM_DQA_AP_PROBE_RESP_QUEUE,
|
|
|
+ if (mvmvif->bcast_sta.tfd_queue_msk & BIT(mvm->probe_queue)) {
|
|
|
+ iwl_mvm_disable_txq(mvm, mvm->probe_queue,
|
|
|
vif->hw_queue[0], IWL_MAX_TID_COUNT,
|
|
|
0);
|
|
|
- mvmvif->bcast_sta.tfd_queue_msk &=
|
|
|
- ~BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE);
|
|
|
+ mvmvif->bcast_sta.tfd_queue_msk &= ~BIT(mvm->probe_queue);
|
|
|
}
|
|
|
|
|
|
- if (mvmvif->bcast_sta.tfd_queue_msk &
|
|
|
- BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE)) {
|
|
|
- iwl_mvm_disable_txq(mvm,
|
|
|
- IWL_MVM_DQA_P2P_DEVICE_QUEUE,
|
|
|
+ if (mvmvif->bcast_sta.tfd_queue_msk & BIT(mvm->p2p_dev_queue)) {
|
|
|
+ iwl_mvm_disable_txq(mvm, mvm->p2p_dev_queue,
|
|
|
vif->hw_queue[0], IWL_MAX_TID_COUNT,
|
|
|
0);
|
|
|
- mvmvif->bcast_sta.tfd_queue_msk &=
|
|
|
- ~BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE);
|
|
|
+ mvmvif->bcast_sta.tfd_queue_msk &= ~BIT(mvm->p2p_dev_queue);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1982,6 +2072,88 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Allocate a new station entry for the multicast station to the given vif,
|
|
|
+ * and send it to the FW.
|
|
|
+ * Note that each AP/GO mac should have its own multicast station.
|
|
|
+ *
|
|
|
+ * @mvm: the mvm component
|
|
|
+ * @vif: the interface to which the multicast station is added
|
|
|
+ */
|
|
|
+int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|
|
+{
|
|
|
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
+ struct iwl_mvm_int_sta *msta = &mvmvif->mcast_sta;
|
|
|
+ static const u8 _maddr[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
+ const u8 *maddr = _maddr;
|
|
|
+ struct iwl_trans_txq_scd_cfg cfg = {
|
|
|
+ .fifo = IWL_MVM_TX_FIFO_MCAST,
|
|
|
+ .sta_id = msta->sta_id,
|
|
|
+ .tid = IWL_MAX_TID_COUNT,
|
|
|
+ .aggregate = false,
|
|
|
+ .frame_limit = IWL_FRAME_LIMIT,
|
|
|
+ };
|
|
|
+ unsigned int timeout = iwl_mvm_get_wd_timeout(mvm, vif, false, false);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ lockdep_assert_held(&mvm->mutex);
|
|
|
+
|
|
|
+ if (!iwl_mvm_is_dqa_supported(mvm))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (WARN_ON(vif->type != NL80211_IFTYPE_AP))
|
|
|
+ return -ENOTSUPP;
|
|
|
+
|
|
|
+ ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr,
|
|
|
+ mvmvif->id, mvmvif->color);
|
|
|
+ if (ret) {
|
|
|
+ iwl_mvm_dealloc_int_sta(mvm, msta);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Enable cab queue after the ADD_STA command is sent.
|
|
|
+ * This is needed for a000 firmware which won't accept SCD_QUEUE_CFG
|
|
|
+ * command with unknown station id.
|
|
|
+ */
|
|
|
+ if (iwl_mvm_has_new_tx_api(mvm)) {
|
|
|
+ int queue = iwl_mvm_tvqm_enable_txq(mvm, vif->cab_queue,
|
|
|
+ msta->sta_id,
|
|
|
+ IWL_MAX_TID_COUNT,
|
|
|
+ timeout);
|
|
|
+ vif->cab_queue = queue;
|
|
|
+ } else {
|
|
|
+ iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
|
|
|
+ &cfg, timeout);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Send the FW a request to remove the station from it's 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)
|
|
|
+{
|
|
|
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ lockdep_assert_held(&mvm->mutex);
|
|
|
+
|
|
|
+ if (!iwl_mvm_is_dqa_supported(mvm))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
|
|
|
+ IWL_MAX_TID_COUNT, 0);
|
|
|
+
|
|
|
+ ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id);
|
|
|
+ if (ret)
|
|
|
+ IWL_WARN(mvm, "Failed sending remove station\n");
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
#define IWL_MAX_RX_BA_SESSIONS 16
|
|
|
|
|
|
static void iwl_mvm_sync_rxq_del_ba(struct iwl_mvm *mvm, u8 baid)
|
|
@@ -2059,6 +2231,7 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm,
|
|
|
reorder_buf->mvm = mvm;
|
|
|
reorder_buf->queue = i;
|
|
|
reorder_buf->sta_id = sta_id;
|
|
|
+ reorder_buf->valid = false;
|
|
|
for (j = 0; j < reorder_buf->buf_size; j++)
|
|
|
__skb_queue_head_init(&reorder_buf->entries[j]);
|
|
|
}
|
|
@@ -2226,7 +2399,9 @@ int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
|
cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
|
|
|
cmd.sta_id = mvm_sta->sta_id;
|
|
|
cmd.add_modify = STA_MODE_MODIFY;
|
|
|
- cmd.modify_mask = STA_MODIFY_QUEUES | STA_MODIFY_TID_DISABLE_TX;
|
|
|
+ if (!iwl_mvm_has_new_tx_api(mvm))
|
|
|
+ cmd.modify_mask = STA_MODIFY_QUEUES;
|
|
|
+ cmd.modify_mask |= STA_MODIFY_TID_DISABLE_TX;
|
|
|
cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
|
|
|
cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg);
|
|
|
|
|
@@ -2426,6 +2601,13 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|
|
* changed from current (become smaller)
|
|
|
*/
|
|
|
if (!alloc_queue && buf_size < mvmsta->max_agg_bufsize) {
|
|
|
+ /*
|
|
|
+ * On new TX API rs and BA manager are offloaded.
|
|
|
+ * For now though, just don't support being reconfigured
|
|
|
+ */
|
|
|
+ if (iwl_mvm_has_new_tx_api(mvm))
|
|
|
+ return -ENOTSUPP;
|
|
|
+
|
|
|
/*
|
|
|
* If reconfiguring an existing queue, it first must be
|
|
|
* drained
|
|
@@ -2675,7 +2857,7 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
|
|
|
* station ID, then use AP's station ID.
|
|
|
*/
|
|
|
if (vif->type == NL80211_IFTYPE_STATION &&
|
|
|
- mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
|
|
|
+ mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
|
|
|
u8 sta_id = mvmvif->ap_sta_id;
|
|
|
|
|
|
sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],
|
|
@@ -2697,68 +2879,97 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
|
|
|
|
|
|
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
|
|
|
struct iwl_mvm_sta *mvm_sta,
|
|
|
- struct ieee80211_key_conf *keyconf, bool mcast,
|
|
|
+ struct ieee80211_key_conf *key, bool mcast,
|
|
|
u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags,
|
|
|
u8 key_offset)
|
|
|
{
|
|
|
- struct iwl_mvm_add_sta_key_cmd cmd = {};
|
|
|
+ union {
|
|
|
+ struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1;
|
|
|
+ struct iwl_mvm_add_sta_key_cmd cmd;
|
|
|
+ } u = {};
|
|
|
__le16 key_flags;
|
|
|
int ret;
|
|
|
u32 status;
|
|
|
u16 keyidx;
|
|
|
- int i;
|
|
|
- u8 sta_id = mvm_sta->sta_id;
|
|
|
+ u64 pn = 0;
|
|
|
+ int i, size;
|
|
|
+ bool new_api = fw_has_api(&mvm->fw->ucode_capa,
|
|
|
+ IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
|
|
|
|
|
|
- keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
|
|
|
+ keyidx = (key->keyidx << STA_KEY_FLG_KEYID_POS) &
|
|
|
STA_KEY_FLG_KEYID_MSK;
|
|
|
key_flags = cpu_to_le16(keyidx);
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_KEY_MAP);
|
|
|
|
|
|
- switch (keyconf->cipher) {
|
|
|
+ switch (key->cipher) {
|
|
|
case WLAN_CIPHER_SUITE_TKIP:
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_TKIP);
|
|
|
- cmd.tkip_rx_tsc_byte2 = tkip_iv32;
|
|
|
- for (i = 0; i < 5; i++)
|
|
|
- cmd.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
|
|
|
- memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
|
|
+ if (new_api) {
|
|
|
+ memcpy((void *)&u.cmd.tx_mic_key,
|
|
|
+ &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
|
|
|
+ IWL_MIC_KEY_SIZE);
|
|
|
+
|
|
|
+ memcpy((void *)&u.cmd.rx_mic_key,
|
|
|
+ &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
|
|
|
+ IWL_MIC_KEY_SIZE);
|
|
|
+ pn = atomic64_read(&key->tx_pn);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ u.cmd_v1.tkip_rx_tsc_byte2 = tkip_iv32;
|
|
|
+ for (i = 0; i < 5; i++)
|
|
|
+ u.cmd_v1.tkip_rx_ttak[i] =
|
|
|
+ cpu_to_le16(tkip_p1k[i]);
|
|
|
+ }
|
|
|
+ memcpy(u.cmd.common.key, key->key, key->keylen);
|
|
|
break;
|
|
|
case WLAN_CIPHER_SUITE_CCMP:
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_CCM);
|
|
|
- memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
|
|
+ memcpy(u.cmd.common.key, key->key, key->keylen);
|
|
|
+ if (new_api)
|
|
|
+ pn = atomic64_read(&key->tx_pn);
|
|
|
break;
|
|
|
case WLAN_CIPHER_SUITE_WEP104:
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_13BYTES);
|
|
|
/* fall through */
|
|
|
case WLAN_CIPHER_SUITE_WEP40:
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_WEP);
|
|
|
- memcpy(cmd.key + 3, keyconf->key, keyconf->keylen);
|
|
|
+ memcpy(u.cmd.common.key + 3, key->key, key->keylen);
|
|
|
break;
|
|
|
case WLAN_CIPHER_SUITE_GCMP_256:
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_KEY_32BYTES);
|
|
|
/* fall through */
|
|
|
case WLAN_CIPHER_SUITE_GCMP:
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_GCMP);
|
|
|
- memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
|
|
+ memcpy(u.cmd.common.key, key->key, key->keylen);
|
|
|
+ if (new_api)
|
|
|
+ pn = atomic64_read(&key->tx_pn);
|
|
|
break;
|
|
|
default:
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_EXT);
|
|
|
- memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
|
|
+ memcpy(u.cmd.common.key, key->key, key->keylen);
|
|
|
}
|
|
|
|
|
|
if (mcast)
|
|
|
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
|
|
|
|
|
- cmd.key_offset = key_offset;
|
|
|
- cmd.key_flags = key_flags;
|
|
|
- cmd.sta_id = sta_id;
|
|
|
+ u.cmd.common.key_offset = key_offset;
|
|
|
+ u.cmd.common.key_flags = key_flags;
|
|
|
+ u.cmd.common.sta_id = mvm_sta->sta_id;
|
|
|
+
|
|
|
+ if (new_api) {
|
|
|
+ u.cmd.transmit_seq_cnt = cpu_to_le64(pn);
|
|
|
+ size = sizeof(u.cmd);
|
|
|
+ } else {
|
|
|
+ size = sizeof(u.cmd_v1);
|
|
|
+ }
|
|
|
|
|
|
status = ADD_STA_SUCCESS;
|
|
|
if (cmd_flags & CMD_ASYNC)
|
|
|
- ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, CMD_ASYNC,
|
|
|
- sizeof(cmd), &cmd);
|
|
|
+ ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, CMD_ASYNC, size,
|
|
|
+ &u.cmd);
|
|
|
else
|
|
|
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
|
|
|
- &cmd, &status);
|
|
|
+ ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size,
|
|
|
+ &u.cmd, &status);
|
|
|
|
|
|
switch (status) {
|
|
|
case ADD_STA_SUCCESS:
|
|
@@ -2858,7 +3069,7 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
|
|
|
return sta->addr;
|
|
|
|
|
|
if (vif->type == NL80211_IFTYPE_STATION &&
|
|
|
- mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
|
|
|
+ mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
|
|
|
u8 sta_id = mvmvif->ap_sta_id;
|
|
|
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
|
|
|
lockdep_is_held(&mvm->mutex));
|
|
@@ -2911,9 +3122,14 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
|
|
|
struct ieee80211_key_conf *keyconf,
|
|
|
bool mcast)
|
|
|
{
|
|
|
- struct iwl_mvm_add_sta_key_cmd cmd = {};
|
|
|
+ union {
|
|
|
+ struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1;
|
|
|
+ struct iwl_mvm_add_sta_key_cmd cmd;
|
|
|
+ } u = {};
|
|
|
+ bool new_api = fw_has_api(&mvm->fw->ucode_capa,
|
|
|
+ IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
|
|
|
__le16 key_flags;
|
|
|
- int ret;
|
|
|
+ int ret, size;
|
|
|
u32 status;
|
|
|
|
|
|
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
|
|
@@ -2924,13 +3140,19 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
|
|
|
if (mcast)
|
|
|
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
|
|
|
|
|
- cmd.key_flags = key_flags;
|
|
|
- cmd.key_offset = keyconf->hw_key_idx;
|
|
|
- cmd.sta_id = sta_id;
|
|
|
+ /*
|
|
|
+ * The fields assigned here are in the same location at the start
|
|
|
+ * of the command, so we can do this union trick.
|
|
|
+ */
|
|
|
+ u.cmd.common.key_flags = key_flags;
|
|
|
+ u.cmd.common.key_offset = keyconf->hw_key_idx;
|
|
|
+ u.cmd.common.sta_id = sta_id;
|
|
|
+
|
|
|
+ size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1);
|
|
|
|
|
|
status = ADD_STA_SUCCESS;
|
|
|
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
|
|
|
- &cmd, &status);
|
|
|
+ ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd,
|
|
|
+ &status);
|
|
|
|
|
|
switch (status) {
|
|
|
case ADD_STA_SUCCESS:
|
|
@@ -3044,7 +3266,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
|
|
{
|
|
|
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
|
|
|
struct iwl_mvm_sta *mvm_sta;
|
|
|
- u8 sta_id = IWL_MVM_STATION_COUNT;
|
|
|
+ u8 sta_id = IWL_MVM_INVALID_STA;
|
|
|
int ret, i;
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
@@ -3301,7 +3523,7 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
/* Block/unblock all the stations of the given mvmvif */
|
|
|
- for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
|
|
|
+ for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
|
|
|
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
|
|
lockdep_is_held(&mvm->mutex));
|
|
|
if (IS_ERR_OR_NULL(sta))
|