aboutsummaryrefslogtreecommitdiffstats
path: root/package/mac80211
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-04-17 20:56:14 +0000
committerFelix Fietkau <nbd@openwrt.org>2011-04-17 20:56:14 +0000
commit032a3504ee4b51f4f09caf234bd724d597855285 (patch)
tree2753df7a95da3387f9cda1e099f67354ddf2dea5 /package/mac80211
parentcbc16e179e43f7e49d5b30187b6c7bb6a7d1efaf (diff)
downloadupstream-032a3504ee4b51f4f09caf234bd724d597855285.tar.gz
upstream-032a3504ee4b51f4f09caf234bd724d597855285.tar.bz2
upstream-032a3504ee4b51f4f09caf234bd724d597855285.zip
ath9k: assign a keycache slot per station for unencrypted links to fix powersave frame filtering
SVN-Revision: 26712
Diffstat (limited to 'package/mac80211')
-rw-r--r--package/mac80211/patches/571-ath9k_assign_unencrypted_ps_keyidx.patch119
1 files changed, 119 insertions, 0 deletions
diff --git a/package/mac80211/patches/571-ath9k_assign_unencrypted_ps_keyidx.patch b/package/mac80211/patches/571-ath9k_assign_unencrypted_ps_keyidx.patch
new file mode 100644
index 0000000000..7996f33f67
--- /dev/null
+++ b/package/mac80211/patches/571-ath9k_assign_unencrypted_ps_keyidx.patch
@@ -0,0 +1,119 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -256,6 +256,8 @@ struct ath_node {
+ #endif
+ struct ath_atx_tid tid[WME_NUM_TID];
+ struct ath_atx_ac ac[WME_NUM_AC];
++ int ps_key;
++
+ u16 maxampdu;
+ u8 mpdudensity;
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1775,18 +1775,37 @@ static int ath9k_sta_add(struct ieee8021
+ struct ieee80211_sta *sta)
+ {
+ struct ath_softc *sc = hw->priv;
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ struct ath_node *an = (struct ath_node *) sta->drv_priv;
++ struct ieee80211_key_conf ps_key = { };
+
+ ath_node_attach(sc, sta);
++ an->ps_key = ath_key_config(common, vif, sta, &ps_key);
+
+ return 0;
+ }
+
++static void ath9k_del_ps_key(struct ath_softc *sc,
++ struct ieee80211_vif *vif,
++ struct ieee80211_sta *sta)
++{
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ struct ath_node *an = (struct ath_node *) sta->drv_priv;
++ struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key };
++
++ if (!an->ps_key)
++ return;
++
++ ath_key_delete(common, &ps_key);
++}
++
+ static int ath9k_sta_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+ {
+ struct ath_softc *sc = hw->priv;
+
++ ath9k_del_ps_key(sc, vif, sta);
+ ath_node_detach(sc, sta);
+
+ return 0;
+@@ -1889,6 +1908,9 @@ static int ath9k_set_key(struct ieee8021
+
+ switch (cmd) {
+ case SET_KEY:
++ if (sta)
++ ath9k_del_ps_key(sc, vif, sta);
++
+ ret = ath_key_config(common, vif, sta, key);
+ if (ret >= 0) {
+ key->hw_key_idx = ret;
+--- a/drivers/net/wireless/ath/key.c
++++ b/drivers/net/wireless/ath/key.c
+@@ -483,6 +483,9 @@ int ath_key_config(struct ath_common *co
+ memset(&hk, 0, sizeof(hk));
+
+ switch (key->cipher) {
++ case 0:
++ hk.kv_type = ATH_CIPHER_CLR;
++ break;
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ hk.kv_type = ATH_CIPHER_WEP;
+@@ -498,7 +501,8 @@ int ath_key_config(struct ath_common *co
+ }
+
+ hk.kv_len = key->keylen;
+- memcpy(hk.kv_val, key->key, key->keylen);
++ if (key->keylen)
++ memcpy(hk.kv_val, key->key, key->keylen);
+
+ if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+ switch (vif->type) {
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1526,7 +1526,7 @@ static void setup_frame_info(struct ieee
+ struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
+ struct ieee80211_hdr *hdr;
+ struct ath_frame_info *fi = get_frame_info(skb);
+- struct ath_node *an;
++ struct ath_node *an = NULL;
+ struct ath_atx_tid *tid;
+ enum ath9k_key_type keytype;
+ u16 seqno = 0;
+@@ -1534,11 +1534,13 @@ static void setup_frame_info(struct ieee
+
+ keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
+
++ if (sta)
++ an = (struct ath_node *) sta->drv_priv;
++
+ hdr = (struct ieee80211_hdr *)skb->data;
+- if (sta && ieee80211_is_data_qos(hdr->frame_control) &&
++ if (an && ieee80211_is_data_qos(hdr->frame_control) &&
+ conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
+
+- an = (struct ath_node *) sta->drv_priv;
+ tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
+
+ /*
+@@ -1554,6 +1556,8 @@ static void setup_frame_info(struct ieee
+ memset(fi, 0, sizeof(*fi));
+ if (hw_key)
+ fi->keyix = hw_key->hw_key_idx;
++ else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
++ fi->keyix = an->ps_key;
+ else
+ fi->keyix = ATH9K_TXKEYIX_INVALID;
+ fi->keytype = keytype;