|
@@ -66,6 +66,115 @@
|
|
|
#include "sta.h"
|
|
|
#include "rs.h"
|
|
|
|
|
|
+static void iwl_mvm_add_sta_cmd_v6_to_v5(struct iwl_mvm_add_sta_cmd_v6 *cmd_v6,
|
|
|
+ struct iwl_mvm_add_sta_cmd_v5 *cmd_v5)
|
|
|
+{
|
|
|
+ memset(cmd_v5, 0, sizeof(*cmd_v5));
|
|
|
+
|
|
|
+ cmd_v5->add_modify = cmd_v6->add_modify;
|
|
|
+ cmd_v5->tid_disable_tx = cmd_v6->tid_disable_tx;
|
|
|
+ cmd_v5->mac_id_n_color = cmd_v6->mac_id_n_color;
|
|
|
+ memcpy(cmd_v5->addr, cmd_v6->addr, ETH_ALEN);
|
|
|
+ cmd_v5->sta_id = cmd_v6->sta_id;
|
|
|
+ cmd_v5->modify_mask = cmd_v6->modify_mask;
|
|
|
+ cmd_v5->station_flags = cmd_v6->station_flags;
|
|
|
+ cmd_v5->station_flags_msk = cmd_v6->station_flags_msk;
|
|
|
+ cmd_v5->add_immediate_ba_tid = cmd_v6->add_immediate_ba_tid;
|
|
|
+ cmd_v5->remove_immediate_ba_tid = cmd_v6->remove_immediate_ba_tid;
|
|
|
+ cmd_v5->add_immediate_ba_ssn = cmd_v6->add_immediate_ba_ssn;
|
|
|
+ cmd_v5->sleep_tx_count = cmd_v6->sleep_tx_count;
|
|
|
+ cmd_v5->sleep_state_flags = cmd_v6->sleep_state_flags;
|
|
|
+ cmd_v5->assoc_id = cmd_v6->assoc_id;
|
|
|
+ cmd_v5->beamform_flags = cmd_v6->beamform_flags;
|
|
|
+ cmd_v5->tfd_queue_msk = cmd_v6->tfd_queue_msk;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+iwl_mvm_add_sta_key_to_add_sta_cmd_v5(struct iwl_mvm_add_sta_key_cmd *key_cmd,
|
|
|
+ struct iwl_mvm_add_sta_cmd_v5 *sta_cmd,
|
|
|
+ u32 mac_id_n_color)
|
|
|
+{
|
|
|
+ memset(sta_cmd, 0, sizeof(*sta_cmd));
|
|
|
+
|
|
|
+ sta_cmd->sta_id = key_cmd->sta_id;
|
|
|
+ sta_cmd->add_modify = STA_MODE_MODIFY;
|
|
|
+ sta_cmd->modify_mask = STA_MODIFY_KEY;
|
|
|
+ sta_cmd->mac_id_n_color = cpu_to_le32(mac_id_n_color);
|
|
|
+
|
|
|
+ sta_cmd->key.key_offset = key_cmd->key_offset;
|
|
|
+ sta_cmd->key.key_flags = key_cmd->key_flags;
|
|
|
+ memcpy(sta_cmd->key.key, key_cmd->key, sizeof(sta_cmd->key.key));
|
|
|
+ sta_cmd->key.tkip_rx_tsc_byte2 = key_cmd->tkip_rx_tsc_byte2;
|
|
|
+ memcpy(sta_cmd->key.tkip_rx_ttak, key_cmd->tkip_rx_ttak,
|
|
|
+ sizeof(sta_cmd->key.tkip_rx_ttak));
|
|
|
+}
|
|
|
+
|
|
|
+static int iwl_mvm_send_add_sta_cmd_status(struct iwl_mvm *mvm,
|
|
|
+ struct iwl_mvm_add_sta_cmd_v6 *cmd,
|
|
|
+ int *status)
|
|
|
+{
|
|
|
+ struct iwl_mvm_add_sta_cmd_v5 cmd_v5;
|
|
|
+
|
|
|
+ if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD)
|
|
|
+ return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(*cmd),
|
|
|
+ cmd, status);
|
|
|
+
|
|
|
+ iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5);
|
|
|
+
|
|
|
+ return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd_v5),
|
|
|
+ &cmd_v5, status);
|
|
|
+}
|
|
|
+
|
|
|
+static int iwl_mvm_send_add_sta_cmd(struct iwl_mvm *mvm, u32 flags,
|
|
|
+ struct iwl_mvm_add_sta_cmd_v6 *cmd)
|
|
|
+{
|
|
|
+ struct iwl_mvm_add_sta_cmd_v5 cmd_v5;
|
|
|
+
|
|
|
+ if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD)
|
|
|
+ return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags,
|
|
|
+ sizeof(*cmd), cmd);
|
|
|
+
|
|
|
+ iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5);
|
|
|
+
|
|
|
+ return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(cmd_v5),
|
|
|
+ &cmd_v5);
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+iwl_mvm_send_add_sta_key_cmd_status(struct iwl_mvm *mvm,
|
|
|
+ struct iwl_mvm_add_sta_key_cmd *cmd,
|
|
|
+ u32 mac_id_n_color,
|
|
|
+ int *status)
|
|
|
+{
|
|
|
+ struct iwl_mvm_add_sta_cmd_v5 sta_cmd;
|
|
|
+
|
|
|
+ if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD)
|
|
|
+ return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY,
|
|
|
+ sizeof(*cmd), cmd, status);
|
|
|
+
|
|
|
+ iwl_mvm_add_sta_key_to_add_sta_cmd_v5(cmd, &sta_cmd, mac_id_n_color);
|
|
|
+
|
|
|
+ return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(sta_cmd),
|
|
|
+ &sta_cmd, status);
|
|
|
+}
|
|
|
+
|
|
|
+static int iwl_mvm_send_add_sta_key_cmd(struct iwl_mvm *mvm,
|
|
|
+ u32 flags,
|
|
|
+ struct iwl_mvm_add_sta_key_cmd *cmd,
|
|
|
+ u32 mac_id_n_color)
|
|
|
+{
|
|
|
+ struct iwl_mvm_add_sta_cmd_v5 sta_cmd;
|
|
|
+
|
|
|
+ if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD)
|
|
|
+ return iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, flags,
|
|
|
+ sizeof(*cmd), cmd);
|
|
|
+
|
|
|
+ iwl_mvm_add_sta_key_to_add_sta_cmd_v5(cmd, &sta_cmd, mac_id_n_color);
|
|
|
+
|
|
|
+ return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(sta_cmd),
|
|
|
+ &sta_cmd);
|
|
|
+}
|
|
|
+
|
|
|
static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm)
|
|
|
{
|
|
|
int sta_id;
|
|
@@ -87,7 +196,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
|
bool update)
|
|
|
{
|
|
|
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
|
|
|
- struct iwl_mvm_add_sta_cmd add_sta_cmd;
|
|
|
+ struct iwl_mvm_add_sta_cmd_v6 add_sta_cmd;
|
|
|
int ret;
|
|
|
u32 status;
|
|
|
u32 agg_size = 0, mpdu_dens = 0;
|
|
@@ -175,8 +284,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
|
cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);
|
|
|
|
|
|
status = ADD_STA_SUCCESS;
|
|
|
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(add_sta_cmd),
|
|
|
- &add_sta_cmd, &status);
|
|
|
+ ret = iwl_mvm_send_add_sta_cmd_status(mvm, &add_sta_cmd, &status);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -256,7 +364,7 @@ int iwl_mvm_update_sta(struct iwl_mvm *mvm,
|
|
|
int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
|
|
bool drain)
|
|
|
{
|
|
|
- struct iwl_mvm_add_sta_cmd cmd = {};
|
|
|
+ struct iwl_mvm_add_sta_cmd_v6 cmd = {};
|
|
|
int ret;
|
|
|
u32 status;
|
|
|
|
|
@@ -269,8 +377,7 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
|
|
cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW);
|
|
|
|
|
|
status = ADD_STA_SUCCESS;
|
|
|
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
|
|
|
- &cmd, &status);
|
|
|
+ ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -469,13 +576,13 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
|
|
|
const u8 *addr,
|
|
|
u16 mac_id, u16 color)
|
|
|
{
|
|
|
- struct iwl_mvm_add_sta_cmd cmd;
|
|
|
+ struct iwl_mvm_add_sta_cmd_v6 cmd;
|
|
|
int ret;
|
|
|
u32 status;
|
|
|
|
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
|
|
- memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd));
|
|
|
+ memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v6));
|
|
|
cmd.sta_id = sta->sta_id;
|
|
|
cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id,
|
|
|
color));
|
|
@@ -485,8 +592,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
|
|
|
if (addr)
|
|
|
memcpy(cmd.addr, addr, ETH_ALEN);
|
|
|
|
|
|
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
|
|
|
- &cmd, &status);
|
|
|
+ ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -614,7 +720,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
|
int tid, u16 ssn, bool start)
|
|
|
{
|
|
|
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
|
|
|
- struct iwl_mvm_add_sta_cmd cmd = {};
|
|
|
+ struct iwl_mvm_add_sta_cmd_v6 cmd = {};
|
|
|
int ret;
|
|
|
u32 status;
|
|
|
|
|
@@ -638,8 +744,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
|
STA_MODIFY_REMOVE_BA_TID;
|
|
|
|
|
|
status = ADD_STA_SUCCESS;
|
|
|
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
|
|
|
- &cmd, &status);
|
|
|
+ ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -674,7 +779,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
|
int tid, u8 queue, bool start)
|
|
|
{
|
|
|
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
|
|
|
- struct iwl_mvm_add_sta_cmd cmd = {};
|
|
|
+ struct iwl_mvm_add_sta_cmd_v6 cmd = {};
|
|
|
int ret;
|
|
|
u32 status;
|
|
|
|
|
@@ -696,8 +801,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
|
cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg);
|
|
|
|
|
|
status = ADD_STA_SUCCESS;
|
|
|
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
|
|
|
- &cmd, &status);
|
|
|
+ ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -987,10 +1091,11 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
|
|
|
u32 cmd_flags)
|
|
|
{
|
|
|
__le16 key_flags;
|
|
|
- struct iwl_mvm_add_sta_cmd cmd = {};
|
|
|
+ struct iwl_mvm_add_sta_key_cmd cmd = {};
|
|
|
int ret, status;
|
|
|
u16 keyidx;
|
|
|
int i;
|
|
|
+ u32 mac_id_n_color = mvm_sta->mac_id_n_color;
|
|
|
|
|
|
keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
|
|
|
STA_KEY_FLG_KEYID_MSK;
|
|
@@ -1000,14 +1105,14 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
|
|
|
switch (keyconf->cipher) {
|
|
|
case WLAN_CIPHER_SUITE_TKIP:
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_TKIP);
|
|
|
- cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
|
|
|
+ cmd.tkip_rx_tsc_byte2 = tkip_iv32;
|
|
|
for (i = 0; i < 5; i++)
|
|
|
- cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
|
|
|
- memcpy(cmd.key.key, keyconf->key, keyconf->keylen);
|
|
|
+ cmd.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
|
|
|
+ memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
|
|
break;
|
|
|
case WLAN_CIPHER_SUITE_CCMP:
|
|
|
key_flags |= cpu_to_le16(STA_KEY_FLG_CCM);
|
|
|
- memcpy(cmd.key.key, keyconf->key, keyconf->keylen);
|
|
|
+ memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
|
|
break;
|
|
|
default:
|
|
|
WARN_ON(1);
|
|
@@ -1017,20 +1122,18 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
|
|
|
if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
|
|
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
|
|
|
|
|
- cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
|
|
|
- cmd.key.key_offset = keyconf->hw_key_idx;
|
|
|
- cmd.key.key_flags = key_flags;
|
|
|
- cmd.add_modify = STA_MODE_MODIFY;
|
|
|
- cmd.modify_mask = STA_MODIFY_KEY;
|
|
|
+ cmd.key_offset = keyconf->hw_key_idx;
|
|
|
+ cmd.key_flags = key_flags;
|
|
|
cmd.sta_id = sta_id;
|
|
|
|
|
|
status = ADD_STA_SUCCESS;
|
|
|
if (cmd_flags == CMD_SYNC)
|
|
|
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
|
|
|
- &cmd, &status);
|
|
|
+ ret = iwl_mvm_send_add_sta_key_cmd_status(mvm, &cmd,
|
|
|
+ mac_id_n_color,
|
|
|
+ &status);
|
|
|
else
|
|
|
- ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC,
|
|
|
- sizeof(cmd), &cmd);
|
|
|
+ ret = iwl_mvm_send_add_sta_key_cmd(mvm, CMD_ASYNC, &cmd,
|
|
|
+ mac_id_n_color);
|
|
|
|
|
|
switch (status) {
|
|
|
case ADD_STA_SUCCESS:
|
|
@@ -1197,7 +1300,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
|
|
struct ieee80211_key_conf *keyconf)
|
|
|
{
|
|
|
struct iwl_mvm_sta *mvm_sta;
|
|
|
- struct iwl_mvm_add_sta_cmd cmd = {};
|
|
|
+ struct iwl_mvm_add_sta_key_cmd cmd = {};
|
|
|
__le16 key_flags;
|
|
|
int ret, status;
|
|
|
u8 sta_id;
|
|
@@ -1252,17 +1355,14 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
|
|
if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
|
|
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
|
|
|
|
|
- cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
|
|
|
- cmd.key.key_flags = key_flags;
|
|
|
- cmd.key.key_offset = keyconf->hw_key_idx;
|
|
|
+ cmd.key_flags = key_flags;
|
|
|
+ cmd.key_offset = keyconf->hw_key_idx;
|
|
|
cmd.sta_id = sta_id;
|
|
|
|
|
|
- cmd.modify_mask = STA_MODIFY_KEY;
|
|
|
- cmd.add_modify = STA_MODE_MODIFY;
|
|
|
-
|
|
|
status = ADD_STA_SUCCESS;
|
|
|
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
|
|
|
- &cmd, &status);
|
|
|
+ ret = iwl_mvm_send_add_sta_key_cmd_status(mvm, &cmd,
|
|
|
+ mvm_sta->mac_id_n_color,
|
|
|
+ &status);
|
|
|
|
|
|
switch (status) {
|
|
|
case ADD_STA_SUCCESS:
|
|
@@ -1309,7 +1409,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
|
|
|
struct ieee80211_sta *sta)
|
|
|
{
|
|
|
struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
|
|
|
- struct iwl_mvm_add_sta_cmd cmd = {
|
|
|
+ struct iwl_mvm_add_sta_cmd_v6 cmd = {
|
|
|
.add_modify = STA_MODE_MODIFY,
|
|
|
.sta_id = mvmsta->sta_id,
|
|
|
.station_flags_msk = cpu_to_le32(STA_FLG_PS),
|
|
@@ -1317,7 +1417,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
|
|
|
};
|
|
|
int ret;
|
|
|
|
|
|
- ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
|
|
|
+ ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd);
|
|
|
if (ret)
|
|
|
IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
|
|
|
}
|
|
@@ -1331,7 +1431,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
|
|
|
(reason == IEEE80211_FRAME_RELEASE_UAPSD) ?
|
|
|
STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL;
|
|
|
struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
|
|
|
- struct iwl_mvm_add_sta_cmd cmd = {
|
|
|
+ struct iwl_mvm_add_sta_cmd_v6 cmd = {
|
|
|
.add_modify = STA_MODE_MODIFY,
|
|
|
.sta_id = mvmsta->sta_id,
|
|
|
.modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
|
|
@@ -1346,7 +1446,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
|
|
|
int ret;
|
|
|
|
|
|
/* TODO: somehow the fw doesn't seem to take PS_POLL into account */
|
|
|
- ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
|
|
|
+ ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd);
|
|
|
if (ret)
|
|
|
IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
|
|
|
}
|