diff options
author | Johannes Berg <johannes.berg@intel.com> | 2014-11-12 17:39:56 -0500 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-11-24 01:30:15 -0500 |
commit | 2f6319d1cf5df2bc01637496296d755e3312c030 (patch) | |
tree | 601f0eddbd05ccb3eff16228b9ec9ce9eb70ae42 | |
parent | bf5da87f60a920599c46382d95b8e9c4ef8da37e (diff) |
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: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/sta.c | 143 |
1 files changed, 79 insertions, 64 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 74a7c9138ce9..f94be3cdeff6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -1072,8 +1072,7 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif, | |||
1072 | static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | 1072 | static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, |
1073 | struct iwl_mvm_sta *mvm_sta, | 1073 | struct iwl_mvm_sta *mvm_sta, |
1074 | struct ieee80211_key_conf *keyconf, | 1074 | struct ieee80211_key_conf *keyconf, |
1075 | u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k, | 1075 | u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags) |
1076 | u32 cmd_flags) | ||
1077 | { | 1076 | { |
1078 | struct iwl_mvm_add_sta_key_cmd cmd = {}; | 1077 | struct iwl_mvm_add_sta_key_cmd cmd = {}; |
1079 | __le16 key_flags; | 1078 | __le16 key_flags; |
@@ -1081,6 +1080,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
1081 | u32 status; | 1080 | u32 status; |
1082 | u16 keyidx; | 1081 | u16 keyidx; |
1083 | int i; | 1082 | int i; |
1083 | u8 sta_id = mvm_sta->sta_id; | ||
1084 | 1084 | ||
1085 | keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & | 1085 | keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & |
1086 | STA_KEY_FLG_KEYID_MSK; | 1086 | STA_KEY_FLG_KEYID_MSK; |
@@ -1196,17 +1196,83 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm, | |||
1196 | return NULL; | 1196 | return NULL; |
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm, | ||
1200 | struct ieee80211_vif *vif, | ||
1201 | struct ieee80211_sta *sta, | ||
1202 | struct ieee80211_key_conf *keyconf) | ||
1203 | { | ||
1204 | struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); | ||
1205 | int ret; | ||
1206 | const u8 *addr; | ||
1207 | struct ieee80211_key_seq seq; | ||
1208 | u16 p1k[5]; | ||
1209 | |||
1210 | switch (keyconf->cipher) { | ||
1211 | case WLAN_CIPHER_SUITE_TKIP: | ||
1212 | addr = iwl_mvm_get_mac_addr(mvm, vif, sta); | ||
1213 | /* get phase 1 key from mac80211 */ | ||
1214 | ieee80211_get_key_rx_seq(keyconf, 0, &seq); | ||
1215 | ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k); | ||
1216 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, | ||
1217 | seq.tkip.iv32, p1k, 0); | ||
1218 | break; | ||
1219 | case WLAN_CIPHER_SUITE_CCMP: | ||
1220 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, | ||
1221 | 0, NULL, 0); | ||
1222 | break; | ||
1223 | default: | ||
1224 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, | ||
1225 | 0, NULL, 0); | ||
1226 | } | ||
1227 | |||
1228 | return ret; | ||
1229 | } | ||
1230 | |||
1231 | static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, | ||
1232 | struct ieee80211_key_conf *keyconf) | ||
1233 | { | ||
1234 | struct iwl_mvm_add_sta_key_cmd cmd = {}; | ||
1235 | __le16 key_flags; | ||
1236 | int ret; | ||
1237 | u32 status; | ||
1238 | |||
1239 | key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & | ||
1240 | STA_KEY_FLG_KEYID_MSK); | ||
1241 | key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP); | ||
1242 | key_flags |= cpu_to_le16(STA_KEY_NOT_VALID); | ||
1243 | |||
1244 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
1245 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); | ||
1246 | |||
1247 | cmd.key_flags = key_flags; | ||
1248 | cmd.key_offset = keyconf->hw_key_idx; | ||
1249 | cmd.sta_id = sta_id; | ||
1250 | |||
1251 | status = ADD_STA_SUCCESS; | ||
1252 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd), | ||
1253 | &cmd, &status); | ||
1254 | |||
1255 | switch (status) { | ||
1256 | case ADD_STA_SUCCESS: | ||
1257 | IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n"); | ||
1258 | break; | ||
1259 | default: | ||
1260 | ret = -EIO; | ||
1261 | IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n"); | ||
1262 | break; | ||
1263 | } | ||
1264 | |||
1265 | return ret; | ||
1266 | } | ||
1267 | |||
1199 | int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, | 1268 | int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, |
1200 | struct ieee80211_vif *vif, | 1269 | struct ieee80211_vif *vif, |
1201 | struct ieee80211_sta *sta, | 1270 | struct ieee80211_sta *sta, |
1202 | struct ieee80211_key_conf *keyconf, | 1271 | struct ieee80211_key_conf *keyconf, |
1203 | bool have_key_offset) | 1272 | bool have_key_offset) |
1204 | { | 1273 | { |
1205 | struct iwl_mvm_sta *mvm_sta; | 1274 | u8 sta_id; |
1206 | int ret; | 1275 | int ret; |
1207 | u8 *addr, sta_id; | ||
1208 | struct ieee80211_key_seq seq; | ||
1209 | u16 p1k[5]; | ||
1210 | 1276 | ||
1211 | lockdep_assert_held(&mvm->mutex); | 1277 | lockdep_assert_held(&mvm->mutex); |
1212 | 1278 | ||
@@ -1235,8 +1301,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, | |||
1235 | } | 1301 | } |
1236 | } | 1302 | } |
1237 | 1303 | ||
1238 | mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv; | 1304 | if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif)) |
1239 | if (WARN_ON_ONCE(mvm_sta->vif != vif)) | ||
1240 | return -EINVAL; | 1305 | return -EINVAL; |
1241 | 1306 | ||
1242 | if (!have_key_offset) { | 1307 | if (!have_key_offset) { |
@@ -1250,24 +1315,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, | |||
1250 | return -ENOSPC; | 1315 | return -ENOSPC; |
1251 | } | 1316 | } |
1252 | 1317 | ||
1253 | switch (keyconf->cipher) { | 1318 | ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf); |
1254 | case WLAN_CIPHER_SUITE_TKIP: | ||
1255 | addr = iwl_mvm_get_mac_addr(mvm, vif, sta); | ||
1256 | /* get phase 1 key from mac80211 */ | ||
1257 | ieee80211_get_key_rx_seq(keyconf, 0, &seq); | ||
1258 | ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k); | ||
1259 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id, | ||
1260 | seq.tkip.iv32, p1k, 0); | ||
1261 | break; | ||
1262 | case WLAN_CIPHER_SUITE_CCMP: | ||
1263 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id, | ||
1264 | 0, NULL, 0); | ||
1265 | break; | ||
1266 | default: | ||
1267 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, | ||
1268 | sta_id, 0, NULL, 0); | ||
1269 | } | ||
1270 | |||
1271 | if (ret) | 1319 | if (ret) |
1272 | __clear_bit(keyconf->hw_key_idx, mvm->fw_key_table); | 1320 | __clear_bit(keyconf->hw_key_idx, mvm->fw_key_table); |
1273 | 1321 | ||
@@ -1283,11 +1331,6 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, | |||
1283 | struct ieee80211_sta *sta, | 1331 | struct ieee80211_sta *sta, |
1284 | struct ieee80211_key_conf *keyconf) | 1332 | struct ieee80211_key_conf *keyconf) |
1285 | { | 1333 | { |
1286 | struct iwl_mvm_sta *mvm_sta; | ||
1287 | struct iwl_mvm_add_sta_key_cmd cmd = {}; | ||
1288 | __le16 key_flags; | ||
1289 | int ret; | ||
1290 | u32 status; | ||
1291 | u8 sta_id; | 1334 | u8 sta_id; |
1292 | 1335 | ||
1293 | lockdep_assert_held(&mvm->mutex); | 1336 | lockdep_assert_held(&mvm->mutex); |
@@ -1301,8 +1344,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, | |||
1301 | if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC) | 1344 | if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC) |
1302 | return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true); | 1345 | return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true); |
1303 | 1346 | ||
1304 | ret = __test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table); | 1347 | if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) { |
1305 | if (!ret) { | ||
1306 | IWL_ERR(mvm, "offset %d not used in fw key table.\n", | 1348 | IWL_ERR(mvm, "offset %d not used in fw key table.\n", |
1307 | keyconf->hw_key_idx); | 1349 | keyconf->hw_key_idx); |
1308 | return -ENOENT; | 1350 | return -ENOENT; |
@@ -1328,37 +1370,10 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, | |||
1328 | } | 1370 | } |
1329 | } | 1371 | } |
1330 | 1372 | ||
1331 | mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv; | 1373 | if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif)) |
1332 | if (WARN_ON_ONCE(mvm_sta->vif != vif)) | ||
1333 | return -EINVAL; | 1374 | return -EINVAL; |
1334 | 1375 | ||
1335 | key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & | 1376 | return __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf); |
1336 | STA_KEY_FLG_KEYID_MSK); | ||
1337 | key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP); | ||
1338 | key_flags |= cpu_to_le16(STA_KEY_NOT_VALID); | ||
1339 | |||
1340 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
1341 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); | ||
1342 | |||
1343 | cmd.key_flags = key_flags; | ||
1344 | cmd.key_offset = keyconf->hw_key_idx; | ||
1345 | cmd.sta_id = sta_id; | ||
1346 | |||
1347 | status = ADD_STA_SUCCESS; | ||
1348 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd), | ||
1349 | &cmd, &status); | ||
1350 | |||
1351 | switch (status) { | ||
1352 | case ADD_STA_SUCCESS: | ||
1353 | IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n"); | ||
1354 | break; | ||
1355 | default: | ||
1356 | ret = -EIO; | ||
1357 | IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n"); | ||
1358 | break; | ||
1359 | } | ||
1360 | |||
1361 | return ret; | ||
1362 | } | 1377 | } |
1363 | 1378 | ||
1364 | void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm, | 1379 | 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 | } | 1398 | } |
1384 | } | 1399 | } |
1385 | 1400 | ||
1386 | mvm_sta = (void *)sta->drv_priv; | 1401 | mvm_sta = iwl_mvm_sta_from_mac80211(sta); |
1387 | iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id, | 1402 | iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, |
1388 | iv32, phase1key, CMD_ASYNC); | 1403 | iv32, phase1key, CMD_ASYNC); |
1389 | rcu_read_unlock(); | 1404 | rcu_read_unlock(); |
1390 | } | 1405 | } |