Commit 299f5462 authored by Reinette Chatre's avatar Reinette Chatre Committed by John W. Linville

iwlwifi: update key flags at time key is set

We need to be symmetrical in what is done when key is set and cleared.
This is important wrt the key flags as they are used during key
clearing and if they are not set when the key is set the key cannot be
cleared completely.

This addresses the many occurences of the WARN found in
iwl_set_tkip_dynamic_key_info() and tracked in
http://www.kerneloops.org/searchweek.php?search=iwl_set_dynamic_key

If calling iwl_set_tkip_dynamic_key_info()/iwl_remove_dynamic_key()
pair a few times in a row will cause that we run out of key space.
This is because the index stored in the key flags is used by
iwl_remove_dynamic_key() to decide if it should remove the key.
Unfortunately the key flags, and hence the key index is currently only
set at the time the key is written to the device (in
iwl_update_tkip_key()) and _not_ in iwl_set_tkip_dynamic_key_info().
Fix this by setting flags in iwl_set_tkip_dynamic_key_info().
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c0f0aac0
...@@ -719,6 +719,14 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, ...@@ -719,6 +719,14 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
{ {
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
__le16 key_flags = 0;
key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
key_flags &= ~STA_KEY_FLG_INVALID;
if (sta_id == priv->hw_params.bcast_sta_id)
key_flags |= STA_KEY_MULTICAST_MSK;
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
...@@ -738,6 +746,9 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, ...@@ -738,6 +746,9 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
"no space for a new key"); "no space for a new key");
priv->stations[sta_id].sta.key.key_flags = key_flags;
/* This copy is acutally not needed: we get the key with each TX */ /* This copy is acutally not needed: we get the key with each TX */
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
...@@ -754,9 +765,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv, ...@@ -754,9 +765,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
{ {
u8 sta_id = IWL_INVALID_STATION; u8 sta_id = IWL_INVALID_STATION;
unsigned long flags; unsigned long flags;
__le16 key_flags = 0;
int i; int i;
DECLARE_MAC_BUF(mac);
sta_id = iwl_find_station(priv, addr); sta_id = iwl_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) { if (sta_id == IWL_INVALID_STATION) {
...@@ -771,16 +780,8 @@ void iwl_update_tkip_key(struct iwl_priv *priv, ...@@ -771,16 +780,8 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
return; return;
} }
key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
key_flags &= ~STA_KEY_FLG_INVALID;
if (sta_id == priv->hw_params.bcast_sta_id)
key_flags |= STA_KEY_MULTICAST_MSK;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->sta_lock, flags);
priv->stations[sta_id].sta.key.key_flags = key_flags;
priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
......
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