Commit 2f6319d1 authored by Johannes Berg's avatar Johannes Berg Committed by Emmanuel Grumbach

iwlwifi: mvm: refactor key add/remove functions

Refactor the key add/remove functions to be able to reuse parts
of them later for RX WEP keys, which need to be uploaded twice.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent bf5da87f
...@@ -1072,8 +1072,7 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif, ...@@ -1072,8 +1072,7 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_sta, struct iwl_mvm_sta *mvm_sta,
struct ieee80211_key_conf *keyconf, struct ieee80211_key_conf *keyconf,
u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k, u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags)
u32 cmd_flags)
{ {
struct iwl_mvm_add_sta_key_cmd cmd = {}; struct iwl_mvm_add_sta_key_cmd cmd = {};
__le16 key_flags; __le16 key_flags;
...@@ -1081,6 +1080,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, ...@@ -1081,6 +1080,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
u32 status; u32 status;
u16 keyidx; u16 keyidx;
int i; int i;
u8 sta_id = mvm_sta->sta_id;
keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
STA_KEY_FLG_KEYID_MSK; STA_KEY_FLG_KEYID_MSK;
...@@ -1196,17 +1196,83 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm, ...@@ -1196,17 +1196,83 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
return NULL; return NULL;
} }
static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *keyconf)
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
int ret;
const u8 *addr;
struct ieee80211_key_seq seq;
u16 p1k[5];
switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
/* get phase 1 key from mac80211 */
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,
seq.tkip.iv32, p1k, 0);
break;
case WLAN_CIPHER_SUITE_CCMP:
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,
0, NULL, 0);
break;
default:
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,
0, NULL, 0);
}
return ret;
}
static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
struct ieee80211_key_conf *keyconf)
{
struct iwl_mvm_add_sta_key_cmd cmd = {};
__le16 key_flags;
int ret;
u32 status;
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
STA_KEY_FLG_KEYID_MSK);
key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
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;
status = ADD_STA_SUCCESS;
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
&cmd, &status);
switch (status) {
case ADD_STA_SUCCESS:
IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
break;
default:
ret = -EIO;
IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
break;
}
return ret;
}
int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct ieee80211_key_conf *keyconf, struct ieee80211_key_conf *keyconf,
bool have_key_offset) bool have_key_offset)
{ {
struct iwl_mvm_sta *mvm_sta; u8 sta_id;
int ret; int ret;
u8 *addr, sta_id;
struct ieee80211_key_seq seq;
u16 p1k[5];
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
...@@ -1235,8 +1301,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -1235,8 +1301,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
} }
} }
mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv; if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
if (WARN_ON_ONCE(mvm_sta->vif != vif))
return -EINVAL; return -EINVAL;
if (!have_key_offset) { if (!have_key_offset) {
...@@ -1250,24 +1315,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, ...@@ -1250,24 +1315,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
return -ENOSPC; return -ENOSPC;
} }
switch (keyconf->cipher) { ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf);
case WLAN_CIPHER_SUITE_TKIP:
addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
/* get phase 1 key from mac80211 */
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
seq.tkip.iv32, p1k, 0);
break;
case WLAN_CIPHER_SUITE_CCMP:
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
0, NULL, 0);
break;
default:
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,
sta_id, 0, NULL, 0);
}
if (ret) if (ret)
__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table); __clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
...@@ -1283,11 +1331,6 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, ...@@ -1283,11 +1331,6 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct ieee80211_key_conf *keyconf) struct ieee80211_key_conf *keyconf)
{ {
struct iwl_mvm_sta *mvm_sta;
struct iwl_mvm_add_sta_key_cmd cmd = {};
__le16 key_flags;
int ret;
u32 status;
u8 sta_id; u8 sta_id;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
...@@ -1301,8 +1344,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, ...@@ -1301,8 +1344,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC) if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true); return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);
ret = __test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table); if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) {
if (!ret) {
IWL_ERR(mvm, "offset %d not used in fw key table.\n", IWL_ERR(mvm, "offset %d not used in fw key table.\n",
keyconf->hw_key_idx); keyconf->hw_key_idx);
return -ENOENT; return -ENOENT;
...@@ -1328,37 +1370,10 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, ...@@ -1328,37 +1370,10 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
} }
} }
mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv; if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
if (WARN_ON_ONCE(mvm_sta->vif != vif))
return -EINVAL; return -EINVAL;
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & return __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf);
STA_KEY_FLG_KEYID_MSK);
key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
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;
status = ADD_STA_SUCCESS;
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
&cmd, &status);
switch (status) {
case ADD_STA_SUCCESS:
IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
break;
default:
ret = -EIO;
IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
break;
}
return ret;
} }
void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm, void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
...@@ -1383,8 +1398,8 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm, ...@@ -1383,8 +1398,8 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
} }
} }
mvm_sta = (void *)sta->drv_priv; mvm_sta = iwl_mvm_sta_from_mac80211(sta);
iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id, iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,
iv32, phase1key, CMD_ASYNC); iv32, phase1key, CMD_ASYNC);
rcu_read_unlock(); rcu_read_unlock();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment