aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-11-12 17:39:56 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-11-24 01:30:15 -0500
commit2f6319d1cf5df2bc01637496296d755e3312c030 (patch)
tree601f0eddbd05ccb3eff16228b9ec9ce9eb70ae42
parentbf5da87f60a920599c46382d95b8e9c4ef8da37e (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.c143
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,
1072static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, 1072static 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
1199static 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
1231static 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
1199int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, 1268int 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
1364void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm, 1379void 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}