iwlwifi: make hw crypto context aware

HW crypto needs to be aware of the context, and there
are different command IDs for the WEP keys per context,
so move the key tracking variables and command IDs into
the context structure.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
This commit is contained in:
Johannes Berg 2010-08-23 10:46:43 +02:00 committed by Wey-Yi Guy
parent 2995bafafd
commit c10afb6e84
7 changed files with 63 additions and 35 deletions

View file

@ -2430,6 +2430,8 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.max_stations = IWL3945_STATION_COUNT; priv->hw_params.max_stations = IWL3945_STATION_COUNT;
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID;
priv->sta_key_max_num = STA_KEY_MAX_NUM;
priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS; priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS;

View file

@ -165,7 +165,7 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
} }
iwl_clear_ucode_stations(priv, ctx); iwl_clear_ucode_stations(priv, ctx);
iwl_restore_stations(priv, ctx); iwl_restore_stations(priv, ctx);
ret = iwl_restore_default_wep_keys(priv); ret = iwl_restore_default_wep_keys(priv, ctx);
if (ret) { if (ret) {
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
return ret; return ret;
@ -197,7 +197,7 @@ int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
iwl_clear_ucode_stations(priv, ctx); iwl_clear_ucode_stations(priv, ctx);
iwl_restore_stations(priv, ctx); iwl_restore_stations(priv, ctx);
ret = iwl_restore_default_wep_keys(priv); ret = iwl_restore_default_wep_keys(priv, ctx);
if (ret) { if (ret) {
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
return ret; return ret;
@ -2222,6 +2222,11 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size; priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size;
priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr; priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;
if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS))
priv->sta_key_max_num = STA_KEY_MAX_NUM;
else
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
/* Copy images into buffers for card's bus-master reads ... */ /* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */ /* Runtime instructions (first block of data in file) */
@ -3548,6 +3553,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
{ {
struct iwl_priv *priv = hw->priv; struct iwl_priv *priv = hw->priv;
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *ctx = vif_priv->ctx;
int ret; int ret;
u8 sta_id; u8 sta_id;
bool is_default_wep_key = false; bool is_default_wep_key = false;
@ -3576,7 +3582,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
key->cipher == WLAN_CIPHER_SUITE_WEP104) && key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
!sta) { !sta) {
if (cmd == SET_KEY) if (cmd == SET_KEY)
is_default_wep_key = !priv->key_mapping_key; is_default_wep_key = !ctx->key_mapping_keys;
else else
is_default_wep_key = is_default_wep_key =
(key->hw_key_idx == HW_KEY_DEFAULT); (key->hw_key_idx == HW_KEY_DEFAULT);
@ -3594,9 +3600,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
break; break;
case DISABLE_KEY: case DISABLE_KEY:
if (is_default_wep_key) if (is_default_wep_key)
ret = iwl_remove_default_wep_key(priv, key); ret = iwl_remove_default_wep_key(priv, ctx, key);
else else
ret = iwl_remove_dynamic_key(priv, key, sta_id); ret = iwl_remove_dynamic_key(priv, ctx, key, sta_id);
IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
break; break;
@ -4209,6 +4215,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1); BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1);
SET_IEEE80211_DEV(hw, &pdev->dev); SET_IEEE80211_DEV(hw, &pdev->dev);

View file

@ -1001,6 +1001,7 @@ struct iwl_qosparam_cmd {
#define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000) #define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000)
#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000) #define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000)
#define STA_KEY_MAX_NUM 8 #define STA_KEY_MAX_NUM 8
#define STA_KEY_MAX_NUM_PAN 16
/* Flags indicate whether to modify vs. don't change various station params */ /* Flags indicate whether to modify vs. don't change various station params */
#define STA_MODIFY_KEY_MASK 0x01 #define STA_MODIFY_KEY_MASK 0x01

View file

@ -1133,6 +1133,10 @@ struct iwl_rxon_context {
u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd; u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd;
u8 qos_cmd; u8 qos_cmd;
u8 wep_key_cmd;
struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
u8 key_mapping_keys;
}; };
struct iwl_priv { struct iwl_priv {
@ -1217,6 +1221,9 @@ struct iwl_priv {
/* command queue number */ /* command queue number */
u8 cmd_queue; u8 cmd_queue;
/* max number of station keys */
u8 sta_key_max_num;
/* EEPROM MAC addresses */ /* EEPROM MAC addresses */
struct mac_address addresses[2]; struct mac_address addresses[2];
@ -1296,8 +1303,6 @@ struct iwl_priv {
spinlock_t sta_lock; spinlock_t sta_lock;
int num_stations; int num_stations;
struct iwl_station_entry stations[IWL_STATION_COUNT]; struct iwl_station_entry stations[IWL_STATION_COUNT];
struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */
u8 key_mapping_key;
unsigned long ucode_key_table; unsigned long ucode_key_table;
/* queue refcounts */ /* queue refcounts */

View file

@ -724,7 +724,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
{ {
int i; int i;
for (i = 0; i < STA_KEY_MAX_NUM; i++) for (i = 0; i < priv->sta_key_max_num; i++)
if (!test_and_set_bit(i, &priv->ucode_key_table)) if (!test_and_set_bit(i, &priv->ucode_key_table))
return i; return i;
@ -732,7 +732,9 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
} }
EXPORT_SYMBOL(iwl_get_free_ucode_key_index); EXPORT_SYMBOL(iwl_get_free_ucode_key_index);
static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
bool send_if_empty)
{ {
int i, not_empty = 0; int i, not_empty = 0;
u8 buff[sizeof(struct iwl_wep_cmd) + u8 buff[sizeof(struct iwl_wep_cmd) +
@ -740,7 +742,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff; struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
size_t cmd_size = sizeof(struct iwl_wep_cmd); size_t cmd_size = sizeof(struct iwl_wep_cmd);
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = REPLY_WEPKEY, .id = ctx->wep_key_cmd,
.data = wep_cmd, .data = wep_cmd,
.flags = CMD_SYNC, .flags = CMD_SYNC,
}; };
@ -752,16 +754,16 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
for (i = 0; i < WEP_KEYS_MAX ; i++) { for (i = 0; i < WEP_KEYS_MAX ; i++) {
wep_cmd->key[i].key_index = i; wep_cmd->key[i].key_index = i;
if (priv->wep_keys[i].key_size) { if (ctx->wep_keys[i].key_size) {
wep_cmd->key[i].key_offset = i; wep_cmd->key[i].key_offset = i;
not_empty = 1; not_empty = 1;
} else { } else {
wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
} }
wep_cmd->key[i].key_size = priv->wep_keys[i].key_size; wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key, memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
priv->wep_keys[i].key_size); ctx->wep_keys[i].key_size);
} }
wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
@ -777,15 +779,17 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
return 0; return 0;
} }
int iwl_restore_default_wep_keys(struct iwl_priv *priv) int iwl_restore_default_wep_keys(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{ {
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->mutex);
return iwl_send_static_wepkey_cmd(priv, 0); return iwl_send_static_wepkey_cmd(priv, ctx, false);
} }
EXPORT_SYMBOL(iwl_restore_default_wep_keys); EXPORT_SYMBOL(iwl_restore_default_wep_keys);
int iwl_remove_default_wep_key(struct iwl_priv *priv, int iwl_remove_default_wep_key(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct ieee80211_key_conf *keyconf) struct ieee80211_key_conf *keyconf)
{ {
int ret; int ret;
@ -795,13 +799,13 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
keyconf->keyidx); keyconf->keyidx);
memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
if (iwl_is_rfkill(priv)) { if (iwl_is_rfkill(priv)) {
IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
/* but keys in device are clear anyway so return success */ /* but keys in device are clear anyway so return success */
return 0; return 0;
} }
ret = iwl_send_static_wepkey_cmd(priv, 1); ret = iwl_send_static_wepkey_cmd(priv, ctx, 1);
IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
keyconf->keyidx, ret); keyconf->keyidx, ret);
@ -827,11 +831,11 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
keyconf->hw_key_idx = HW_KEY_DEFAULT; keyconf->hw_key_idx = HW_KEY_DEFAULT;
priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
keyconf->keylen); keyconf->keylen);
ret = iwl_send_static_wepkey_cmd(priv, 0); ret = iwl_send_static_wepkey_cmd(priv, ctx, false);
IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
keyconf->keylen, keyconf->keyidx, ret); keyconf->keylen, keyconf->keyidx, ret);
@ -1029,8 +1033,9 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
EXPORT_SYMBOL(iwl_update_tkip_key); EXPORT_SYMBOL(iwl_update_tkip_key);
int iwl_remove_dynamic_key(struct iwl_priv *priv, int iwl_remove_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf, struct iwl_rxon_context *ctx,
u8 sta_id) struct ieee80211_key_conf *keyconf,
u8 sta_id)
{ {
unsigned long flags; unsigned long flags;
u16 key_flags; u16 key_flags;
@ -1039,7 +1044,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->mutex);
priv->key_mapping_key--; ctx->key_mapping_keys--;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->sta_lock, flags);
key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
@ -1098,7 +1103,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
lockdep_assert_held(&priv->mutex); lockdep_assert_held(&priv->mutex);
priv->key_mapping_key++; ctx->key_mapping_keys++;
keyconf->hw_key_idx = HW_KEY_DYNAMIC; keyconf->hw_key_idx = HW_KEY_DYNAMIC;
switch (keyconf->cipher) { switch (keyconf->cipher) {

View file

@ -44,14 +44,16 @@
int iwl_remove_default_wep_key(struct iwl_priv *priv, int iwl_remove_default_wep_key(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct ieee80211_key_conf *key); struct ieee80211_key_conf *key);
int iwl_set_default_wep_key(struct iwl_priv *priv, int iwl_set_default_wep_key(struct iwl_priv *priv,
struct iwl_rxon_context *ctx, struct iwl_rxon_context *ctx,
struct ieee80211_key_conf *key); struct ieee80211_key_conf *key);
int iwl_restore_default_wep_keys(struct iwl_priv *priv); int iwl_restore_default_wep_keys(struct iwl_priv *priv,
struct iwl_rxon_context *ctx);
int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct ieee80211_key_conf *key, u8 sta_id); struct ieee80211_key_conf *key, u8 sta_id);
int iwl_remove_dynamic_key(struct iwl_priv *priv, int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct ieee80211_key_conf *key, u8 sta_id); struct ieee80211_key_conf *key, u8 sta_id);
void iwl_update_tkip_key(struct iwl_priv *priv, void iwl_update_tkip_key(struct iwl_priv *priv,
struct iwl_rxon_context *ctx, struct iwl_rxon_context *ctx,
@ -97,20 +99,25 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
static inline void iwl_clear_driver_stations(struct iwl_priv *priv) static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
{ {
unsigned long flags; unsigned long flags;
struct iwl_rxon_context *ctx;
spin_lock_irqsave(&priv->sta_lock, flags); spin_lock_irqsave(&priv->sta_lock, flags);
memset(priv->stations, 0, sizeof(priv->stations)); memset(priv->stations, 0, sizeof(priv->stations));
priv->num_stations = 0; priv->num_stations = 0;
/*
* Remove all key information that is not stored as part of station
* information since mac80211 may not have had a
* chance to remove all the keys. When device is reconfigured by
* mac80211 after an error all keys will be reconfigured.
*/
priv->ucode_key_table = 0; priv->ucode_key_table = 0;
priv->key_mapping_key = 0;
memset(priv->wep_keys, 0, sizeof(priv->wep_keys)); for_each_context(priv, ctx) {
/*
* Remove all key information that is not stored as part
* of station information since mac80211 may not have had
* a chance to remove all the keys. When device is
* reconfigured by mac80211 after an error all keys will
* be reconfigured.
*/
memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
ctx->key_mapping_keys = 0;
}
spin_unlock_irqrestore(&priv->sta_lock, flags); spin_unlock_irqrestore(&priv->sta_lock, flags);
} }

View file

@ -4022,6 +4022,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC; priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
/* /*
* Disabling hardware scan means that mac80211 will perform scans * Disabling hardware scan means that mac80211 will perform scans