From 032a3504ee4b51f4f09caf234bd724d597855285 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 17 Apr 2011 20:56:14 +0000 Subject: [PATCH] ath9k: assign a keycache slot per station for unencrypted links to fix powersave frame filtering SVN-Revision: 26712 --- ...1-ath9k_assign_unencrypted_ps_keyidx.patch | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 package/mac80211/patches/571-ath9k_assign_unencrypted_ps_keyidx.patch 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;