aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-03-19 19:41:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-03-25 16:41:52 -0400
commitdeb09c435e3f947f8b2c9d5df6a9c0a5b472b125 (patch)
tree0c51f22a35512b3f64ec96fd137265a82b71547a /drivers
parentbf85ea4fbecab278c63f02fd102b33cc6cb21eb9 (diff)
iwlwifi-2.6: Cleans up set_key flow
This patch cleans up the set_key flow. Rxon with hw encryption bit set is not sent upon each call to set_key. Separation is made between global key (WEP) and dynamic key (TKIP + CCMP and WEP in some cases). Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-commands.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c165
2 files changed, 110 insertions, 56 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
index 1025ffeb8fa8..085d8137bfb8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
@@ -741,6 +741,7 @@ struct iwl4965_qosparam_cmd {
741/* wep key in STA: 5-bytes (0) or 13-bytes (1) */ 741/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
742#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000) 742#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000)
743#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000) 743#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000)
744#define STA_KEY_MAX_NUM 8
744 745
745/* Flags indicate whether to modify vs. don't change various station params */ 746/* Flags indicate whether to modify vs. don't change various station params */
746#define STA_MODIFY_KEY_MASK 0x01 747#define STA_MODIFY_KEY_MASK 0x01
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 9cf1f204666d..fc3e23a2d8eb 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -796,6 +796,17 @@ out:
796 return ret; 796 return ret;
797} 797}
798 798
799static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
800{
801 struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
802
803 if (hw_decrypt)
804 rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
805 else
806 rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
807
808}
809
799int iwl4965_send_cmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) 810int iwl4965_send_cmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd)
800{ 811{
801 if (cmd->meta.flags & CMD_ASYNC) 812 if (cmd->meta.flags & CMD_ASYNC)
@@ -1124,6 +1135,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
1124 le16_to_cpu(priv->staging_rxon.channel), 1135 le16_to_cpu(priv->staging_rxon.channel),
1125 print_mac(mac, priv->staging_rxon.bssid_addr)); 1136 print_mac(mac, priv->staging_rxon.bssid_addr));
1126 1137
1138 iwl4965_set_rxon_hwcrypto(priv, priv->cfg->mod_params->hw_crypto);
1127 /* Apply the new configuration */ 1139 /* Apply the new configuration */
1128 rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON, 1140 rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON,
1129 sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon); 1141 sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon);
@@ -1336,33 +1348,36 @@ int iwl4965_send_add_station(struct iwl_priv *priv,
1336 return rc; 1348 return rc;
1337} 1349}
1338 1350
1339static int iwl4965_update_sta_key_info(struct iwl_priv *priv, 1351static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
1340 struct ieee80211_key_conf *keyconf, 1352 struct ieee80211_key_conf *keyconf,
1341 u8 sta_id) 1353 u8 sta_id)
1342{ 1354{
1343 unsigned long flags; 1355 unsigned long flags;
1344 __le16 key_flags = 0; 1356 __le16 key_flags = 0;
1345 1357
1346 switch (keyconf->alg) { 1358 key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
1347 case ALG_CCMP: 1359 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
1348 key_flags |= STA_KEY_FLG_CCMP; 1360
1349 key_flags |= cpu_to_le16( 1361 if (sta_id == priv->hw_setting.bcast_sta_id)
1350 keyconf->keyidx << STA_KEY_FLG_KEYID_POS); 1362 key_flags |= STA_KEY_MULTICAST_MSK;
1351 key_flags &= ~STA_KEY_FLG_INVALID; 1363
1352 break; 1364 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
1353 case ALG_TKIP: 1365 keyconf->hw_key_idx = keyconf->keyidx;
1354 case ALG_WEP: 1366
1355 default: 1367 key_flags &= ~STA_KEY_FLG_INVALID;
1356 return -EINVAL; 1368
1357 }
1358 spin_lock_irqsave(&priv->sta_lock, flags); 1369 spin_lock_irqsave(&priv->sta_lock, flags);
1359 priv->stations[sta_id].keyinfo.alg = keyconf->alg; 1370 priv->stations[sta_id].keyinfo.alg = keyconf->alg;
1360 priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; 1371 priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
1372
1361 memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 1373 memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
1362 keyconf->keylen); 1374 keyconf->keylen);
1363 1375
1364 memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 1376 memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
1365 keyconf->keylen); 1377 keyconf->keylen);
1378
1379 priv->stations[sta_id].sta.key.key_offset
1380 = (sta_id % STA_KEY_MAX_NUM);/*FIXME*/
1366 priv->stations[sta_id].sta.key.key_flags = key_flags; 1381 priv->stations[sta_id].sta.key.key_flags = key_flags;
1367 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; 1382 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
1368 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1383 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
@@ -1370,8 +1385,15 @@ static int iwl4965_update_sta_key_info(struct iwl_priv *priv,
1370 spin_unlock_irqrestore(&priv->sta_lock, flags); 1385 spin_unlock_irqrestore(&priv->sta_lock, flags);
1371 1386
1372 IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); 1387 IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
1373 iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); 1388 return iwl4965_send_add_station(priv,
1374 return 0; 1389 &priv->stations[sta_id].sta, CMD_ASYNC);
1390}
1391
1392static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv,
1393 struct ieee80211_key_conf *keyconf,
1394 u8 sta_id)
1395{
1396 return -EOPNOTSUPP;
1375} 1397}
1376 1398
1377static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) 1399static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
@@ -1391,6 +1413,46 @@ static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
1391 return 0; 1413 return 0;
1392} 1414}
1393 1415
1416static int iwl4965_set_dynamic_key(struct iwl_priv *priv,
1417 struct ieee80211_key_conf *key, u8 sta_id)
1418{
1419 int ret;
1420
1421 switch (key->alg) {
1422 case ALG_CCMP:
1423 ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id);
1424 break;
1425 case ALG_TKIP:
1426 ret = iwl4965_set_tkip_dynamic_key_info(priv, key, sta_id);
1427 break;
1428 case ALG_WEP:
1429 ret = -EOPNOTSUPP;
1430 break;
1431 default:
1432 IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
1433 ret = -EINVAL;
1434 }
1435
1436 return ret;
1437}
1438
1439static int iwl4965_remove_static_key(struct iwl_priv *priv)
1440{
1441 int ret = -EOPNOTSUPP;
1442
1443 return ret;
1444}
1445
1446static int iwl4965_set_static_key(struct iwl_priv *priv,
1447 struct ieee80211_key_conf *key)
1448{
1449 if (key->alg == ALG_WEP)
1450 return -EOPNOTSUPP;
1451
1452 IWL_ERROR("Static key invalid: alg %d\n", key->alg);
1453 return -EINVAL;
1454}
1455
1394static void iwl4965_clear_free_frames(struct iwl_priv *priv) 1456static void iwl4965_clear_free_frames(struct iwl_priv *priv)
1395{ 1457{
1396 struct list_head *element; 1458 struct list_head *element;
@@ -2122,17 +2184,6 @@ static int iwl4965_scan_initiate(struct iwl_priv *priv)
2122 return 0; 2184 return 0;
2123} 2185}
2124 2186
2125static int iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
2126{
2127 struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
2128
2129 if (hw_decrypt)
2130 rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
2131 else
2132 rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
2133
2134 return 0;
2135}
2136 2187
2137static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv, 2188static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv,
2138 enum ieee80211_band band) 2189 enum ieee80211_band band)
@@ -2276,9 +2327,9 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
2276 struct ieee80211_tx_control *ctl, 2327 struct ieee80211_tx_control *ctl,
2277 struct iwl4965_cmd *cmd, 2328 struct iwl4965_cmd *cmd,
2278 struct sk_buff *skb_frag, 2329 struct sk_buff *skb_frag,
2279 int last_frag) 2330 int sta_id)
2280{ 2331{
2281 struct iwl4965_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo; 2332 struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
2282 2333
2283 switch (keyinfo->alg) { 2334 switch (keyinfo->alg) {
2284 case ALG_CCMP: 2335 case ALG_CCMP:
@@ -2614,7 +2665,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
2614 iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); 2665 iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
2615 2666
2616 if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) 2667 if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
2617 iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0); 2668 iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, sta_id);
2618 2669
2619 /* Set up TFD's 2nd entry to point directly to remainder of skb, 2670 /* Set up TFD's 2nd entry to point directly to remainder of skb,
2620 * if any (802.11 null frames have no payload). */ 2671 * if any (802.11 null frames have no payload). */
@@ -7121,8 +7172,9 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
7121{ 7172{
7122 struct iwl_priv *priv = hw->priv; 7173 struct iwl_priv *priv = hw->priv;
7123 DECLARE_MAC_BUF(mac); 7174 DECLARE_MAC_BUF(mac);
7124 int rc = 0; 7175 int ret = 0;
7125 u8 sta_id; 7176 u8 sta_id = IWL_INVALID_STATION;
7177 u8 static_key;
7126 7178
7127 IWL_DEBUG_MAC80211("enter\n"); 7179 IWL_DEBUG_MAC80211("enter\n");
7128 7180
@@ -7135,44 +7187,45 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
7135 /* only support pairwise keys */ 7187 /* only support pairwise keys */
7136 return -EOPNOTSUPP; 7188 return -EOPNOTSUPP;
7137 7189
7138 sta_id = iwl4965_hw_find_station(priv, addr); 7190 /* FIXME: need to differenciate between static and dynamic key
7139 if (sta_id == IWL_INVALID_STATION) { 7191 * in the level of mac80211 */
7140 IWL_DEBUG_MAC80211("leave - %s not in station map.\n", 7192 static_key = !iwl4965_is_associated(priv);
7141 print_mac(mac, addr));
7142 return -EINVAL;
7143 }
7144 7193
7145 mutex_lock(&priv->mutex); 7194 if (!static_key) {
7195 sta_id = iwl4965_hw_find_station(priv, addr);
7196 if (sta_id == IWL_INVALID_STATION) {
7197 IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
7198 print_mac(mac, addr));
7199 return -EINVAL;
7200 }
7201 }
7146 7202
7147 iwl4965_scan_cancel_timeout(priv, 100); 7203 iwl4965_scan_cancel_timeout(priv, 100);
7148 7204
7149 switch (cmd) { 7205 switch (cmd) {
7150 case SET_KEY: 7206 case SET_KEY:
7151 rc = iwl4965_update_sta_key_info(priv, key, sta_id); 7207 if (static_key)
7152 if (!rc) { 7208 ret = iwl4965_set_static_key(priv, key);
7153 iwl4965_set_rxon_hwcrypto(priv, 1); 7209 else
7154 iwl4965_commit_rxon(priv); 7210 ret = iwl4965_set_dynamic_key(priv, key, sta_id);
7155 key->hw_key_idx = sta_id; 7211
7156 IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n"); 7212 IWL_DEBUG_MAC80211("enable hwcrypto key\n");
7157 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
7158 }
7159 break; 7213 break;
7160 case DISABLE_KEY: 7214 case DISABLE_KEY:
7161 rc = iwl4965_clear_sta_key_info(priv, sta_id); 7215 if (static_key)
7162 if (!rc) { 7216 ret = iwl4965_remove_static_key(priv);
7163 iwl4965_set_rxon_hwcrypto(priv, 0); 7217 else
7164 iwl4965_commit_rxon(priv); 7218 ret = iwl4965_clear_sta_key_info(priv, sta_id);
7165 IWL_DEBUG_MAC80211("disable hwcrypto key\n"); 7219
7166 } 7220 IWL_DEBUG_MAC80211("disable hwcrypto key\n");
7167 break; 7221 break;
7168 default: 7222 default:
7169 rc = -EINVAL; 7223 ret = -EINVAL;
7170 } 7224 }
7171 7225
7172 IWL_DEBUG_MAC80211("leave\n"); 7226 IWL_DEBUG_MAC80211("leave\n");
7173 mutex_unlock(&priv->mutex);
7174 7227
7175 return rc; 7228 return ret;
7176} 7229}
7177 7230
7178static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, 7231static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,