--- 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;