Commit e0f8c2a9 authored by Bruno Randolf's avatar Bruno Randolf Committed by John W. Linville

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: default avatarBruno Randolf <br1@einfach.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 1bba5b73
...@@ -314,6 +314,9 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ...@@ -314,6 +314,9 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
} }
/* Crypto settings */ /* 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 && ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 &&
(ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
!AR5K_EEPROM_AES_DIS(ee->ee_misc5)); !AR5K_EEPROM_AES_DIS(ee->ee_misc5));
......
...@@ -2570,6 +2570,7 @@ static int ...@@ -2570,6 +2570,7 @@ static int
ath5k_init(struct ath5k_softc *sc) ath5k_init(struct ath5k_softc *sc)
{ {
struct ath5k_hw *ah = sc->ah; struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
int ret, i; int ret, i;
mutex_lock(&sc->lock); mutex_lock(&sc->lock);
...@@ -2605,8 +2606,8 @@ ath5k_init(struct ath5k_softc *sc) ...@@ -2605,8 +2606,8 @@ ath5k_init(struct ath5k_softc *sc)
* Reset the key cache since some parts do not reset the * Reset the key cache since some parts do not reset the
* contents on initial power up or resume from suspend. * contents on initial power up or resume from suspend.
*/ */
for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) for (i = 0; i < common->keymax; i++)
ath5k_hw_reset_key(ah, i); ath_hw_keyreset(common, (u16)i);
ath5k_hw_set_ack_bitrate_high(ah, true); ath5k_hw_set_ack_bitrate_high(ah, true);
ret = 0; ret = 0;
...@@ -3287,9 +3288,6 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -3287,9 +3288,6 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (modparam_nohwcrypt) if (modparam_nohwcrypt)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (sc->opmode == NL80211_IFTYPE_AP)
return -EOPNOTSUPP;
switch (key->cipher) { switch (key->cipher) {
case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_WEP104:
...@@ -3298,7 +3296,6 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -3298,7 +3296,6 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
if (sc->ah->ah_aes_support) if (sc->ah->ah_aes_support)
break; break;
return -EOPNOTSUPP; return -EOPNOTSUPP;
default: default:
WARN_ON(1); WARN_ON(1);
...@@ -3309,27 +3306,25 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -3309,27 +3306,25 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
switch (cmd) { switch (cmd) {
case SET_KEY: case SET_KEY:
ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, ret = ath_key_config(common, vif, sta, key);
sta ? sta->addr : NULL); if (ret >= 0) {
if (ret) { key->hw_key_idx = ret;
ATH5K_ERR(sc, "can't set the key\n"); /* push IV and Michael MIC generation to stack */
goto unlock; 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; break;
case DISABLE_KEY: case DISABLE_KEY:
ath5k_hw_reset_key(sc->ah, key->keyidx); ath_key_delete(common, key);
__clear_bit(key->keyidx, common->keymap);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
goto unlock;
} }
unlock:
mmiowb(); mmiowb();
mutex_unlock(&sc->lock); mutex_unlock(&sc->lock);
return ret; return ret;
......
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