summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorBruno Randolf <br1@einfach.org>2010-09-08 16:04:43 +0900
committerJohn W. Linville <linville@tuxdriver.com>2010-09-16 15:19:45 -0400
commite0f8c2a9b879e1e65d588a40a3c88db69a7d6956 (patch)
tree414c5fb35665de34c8d56015887d73b48f30501f /drivers/net/wireless/ath
parent1bba5b7329e15555dab90071b24ca84d0afcc635 (diff)
ath5k: Use common ath key management functions
Use common ath key management functions in ath5k. This fixes problems with HW encryption in AP mode, which was broken in the ath5k implementation. Before (with the ath5k implementation) only one client could connect to the AP using HW encryption and WPA. When a second client connected, the first client was not able to send/receive any more packets. Because of the problems with HW encryption, software encryption was always used in AP mode, which resulted in a high CPU load (and/or low thruput) on embedded devices. Instead of trying to fix the implementation in ath5k it makes more sense to share the code with ath9k. This also enables HW encryption for AP mode again. Signed-off-by: Bruno Randolf <br1@einfach.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c3
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c33
2 files changed, 17 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index aabad4f13e2..eb125d69fb7 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -314,6 +314,9 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
}
/* Crypto settings */
+ common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
+ AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
+
ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 &&
(ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
!AR5K_EEPROM_AES_DIS(ee->ee_misc5));
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 45789c8990d..7933646583a 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2570,6 +2570,7 @@ static int
ath5k_init(struct ath5k_softc *sc)
{
struct ath5k_hw *ah = sc->ah;
+ struct ath_common *common = ath5k_hw_common(ah);
int ret, i;
mutex_lock(&sc->lock);
@@ -2605,8 +2606,8 @@ ath5k_init(struct ath5k_softc *sc)
* Reset the key cache since some parts do not reset the
* contents on initial power up or resume from suspend.
*/
- for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
- ath5k_hw_reset_key(ah, i);
+ for (i = 0; i < common->keymax; i++)
+ ath_hw_keyreset(common, (u16)i);
ath5k_hw_set_ack_bitrate_high(ah, true);
ret = 0;
@@ -3287,9 +3288,6 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (modparam_nohwcrypt)
return -EOPNOTSUPP;
- if (sc->opmode == NL80211_IFTYPE_AP)
- return -EOPNOTSUPP;
-
switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
@@ -3298,7 +3296,6 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
case WLAN_CIPHER_SUITE_CCMP:
if (sc->ah->ah_aes_support)
break;
-
return -EOPNOTSUPP;
default:
WARN_ON(1);
@@ -3309,27 +3306,25 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
switch (cmd) {
case SET_KEY:
- ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
- sta ? sta->addr : NULL);
- if (ret) {
- ATH5K_ERR(sc, "can't set the key\n");
- goto unlock;
+ ret = ath_key_config(common, vif, sta, key);
+ if (ret >= 0) {
+ key->hw_key_idx = ret;
+ /* push IV and Michael MIC generation to stack */
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
+ ret = 0;
}
- __set_bit(key->keyidx, common->keymap);
- key->hw_key_idx = key->keyidx;
- key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
- IEEE80211_KEY_FLAG_GENERATE_MMIC);
break;
case DISABLE_KEY:
- ath5k_hw_reset_key(sc->ah, key->keyidx);
- __clear_bit(key->keyidx, common->keymap);
+ ath_key_delete(common, key);
break;
default:
ret = -EINVAL;
- goto unlock;
}
-unlock:
mmiowb();
mutex_unlock(&sc->lock);
return ret;