ath9k: merge powersave fix from r26712
[openwrt-10.03/.git] / package / mac80211 / patches / 571-ath9k_assign_unencrypted_ps_keyidx.patch
1 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
2 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
3 @@ -256,6 +256,8 @@ struct ath_node {
4  #endif
5         struct ath_atx_tid tid[WME_NUM_TID];
6         struct ath_atx_ac ac[WME_NUM_AC];
7 +       int ps_key;
8 +
9         u16 maxampdu;
10         u8 mpdudensity;
11  
12 --- a/drivers/net/wireless/ath/ath9k/main.c
13 +++ b/drivers/net/wireless/ath/ath9k/main.c
14 @@ -1775,18 +1775,37 @@ static int ath9k_sta_add(struct ieee8021
15                          struct ieee80211_sta *sta)
16  {
17         struct ath_softc *sc = hw->priv;
18 +       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
19 +       struct ath_node *an = (struct ath_node *) sta->drv_priv;
20 +       struct ieee80211_key_conf ps_key = { };
21  
22         ath_node_attach(sc, sta);
23 +       an->ps_key = ath_key_config(common, vif, sta, &ps_key);
24  
25         return 0;
26  }
27  
28 +static void ath9k_del_ps_key(struct ath_softc *sc,
29 +                            struct ieee80211_vif *vif,
30 +                            struct ieee80211_sta *sta)
31 +{
32 +       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
33 +       struct ath_node *an = (struct ath_node *) sta->drv_priv;
34 +       struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key };
35 +
36 +       if (!an->ps_key)
37 +           return;
38 +
39 +       ath_key_delete(common, &ps_key);
40 +}
41 +
42  static int ath9k_sta_remove(struct ieee80211_hw *hw,
43                             struct ieee80211_vif *vif,
44                             struct ieee80211_sta *sta)
45  {
46         struct ath_softc *sc = hw->priv;
47  
48 +       ath9k_del_ps_key(sc, vif, sta);
49         ath_node_detach(sc, sta);
50  
51         return 0;
52 @@ -1889,6 +1908,9 @@ static int ath9k_set_key(struct ieee8021
53  
54         switch (cmd) {
55         case SET_KEY:
56 +               if (sta)
57 +                       ath9k_del_ps_key(sc, vif, sta);
58 +
59                 ret = ath_key_config(common, vif, sta, key);
60                 if (ret >= 0) {
61                         key->hw_key_idx = ret;
62 --- a/drivers/net/wireless/ath/key.c
63 +++ b/drivers/net/wireless/ath/key.c
64 @@ -483,6 +483,9 @@ int ath_key_config(struct ath_common *co
65         memset(&hk, 0, sizeof(hk));
66  
67         switch (key->cipher) {
68 +       case 0:
69 +               hk.kv_type = ATH_CIPHER_CLR;
70 +               break;
71         case WLAN_CIPHER_SUITE_WEP40:
72         case WLAN_CIPHER_SUITE_WEP104:
73                 hk.kv_type = ATH_CIPHER_WEP;
74 @@ -498,7 +501,8 @@ int ath_key_config(struct ath_common *co
75         }
76  
77         hk.kv_len = key->keylen;
78 -       memcpy(hk.kv_val, key->key, key->keylen);
79 +       if (key->keylen)
80 +               memcpy(hk.kv_val, key->key, key->keylen);
81  
82         if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
83                 switch (vif->type) {
84 --- a/drivers/net/wireless/ath/ath9k/xmit.c
85 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
86 @@ -1526,7 +1526,7 @@ static void setup_frame_info(struct ieee
87         struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
88         struct ieee80211_hdr *hdr;
89         struct ath_frame_info *fi = get_frame_info(skb);
90 -       struct ath_node *an;
91 +       struct ath_node *an = NULL;
92         struct ath_atx_tid *tid;
93         enum ath9k_key_type keytype;
94         u16 seqno = 0;
95 @@ -1534,11 +1534,13 @@ static void setup_frame_info(struct ieee
96  
97         keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
98  
99 +       if (sta)
100 +               an = (struct ath_node *) sta->drv_priv;
101 +
102         hdr = (struct ieee80211_hdr *)skb->data;
103 -       if (sta && ieee80211_is_data_qos(hdr->frame_control) &&
104 +       if (an && ieee80211_is_data_qos(hdr->frame_control) &&
105                 conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
106  
107 -               an = (struct ath_node *) sta->drv_priv;
108                 tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
109  
110                 /*
111 @@ -1554,6 +1556,8 @@ static void setup_frame_info(struct ieee
112         memset(fi, 0, sizeof(*fi));
113         if (hw_key)
114                 fi->keyix = hw_key->hw_key_idx;
115 +       else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
116 +               fi->keyix = an->ps_key;
117         else
118                 fi->keyix = ATH9K_TXKEYIX_INVALID;
119         fi->keytype = keytype;