mac80211: update brcmfmac including missing boardrev workaround
[openwrt.git] / package / kernel / mac80211 / patches / 344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch
1 From: Hante Meuleman <meuleman@broadcom.com>
2 Date: Wed, 17 Feb 2016 11:27:03 +0100
3 Subject: [PATCH] brcmfmac: add wowl gtk rekeying offload support
4
5 This patch adds support for gtk rekeying offload and for gtk
6 rekeying failure during wowl mode.
7
8 Reviewed-by: Arend Van Spriel <arend@broadcom.com>
9 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
10 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
11 Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
12 Signed-off-by: Arend van Spriel <arend@broadcom.com>
13 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
14 ---
15
16 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
17 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
18 @@ -3526,6 +3526,10 @@ static void brcmf_report_wowl_wakeind(st
19                         else
20                                 wakeup_data.net_detect = cfg->wowl.nd_info;
21                 }
22 +               if (wakeind & BRCMF_WOWL_GTK_FAILURE) {
23 +                       brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_GTK_FAILURE\n");
24 +                       wakeup_data.gtk_rekey_failure = true;
25 +               }
26         } else {
27                 wakeup = NULL;
28         }
29 @@ -3607,6 +3611,8 @@ static void brcmf_configure_wowl(struct
30                 brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
31                                     brcmf_wowl_nd_results);
32         }
33 +       if (wowl->gtk_rekey_failure)
34 +               wowl_config |= BRCMF_WOWL_GTK_FAILURE;
35         if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
36                 wowl_config |= BRCMF_WOWL_UNASSOC;
37  
38 @@ -4874,7 +4880,32 @@ static int brcmf_cfg80211_tdls_oper(stru
39         return ret;
40  }
41  
42 -static struct cfg80211_ops wl_cfg80211_ops = {
43 +#ifdef CONFIG_PM
44 +static int
45 +brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
46 +                             struct cfg80211_gtk_rekey_data *gtk)
47 +{
48 +       struct brcmf_if *ifp = netdev_priv(ndev);
49 +       struct brcmf_gtk_keyinfo_le gtk_le;
50 +       int ret;
51 +
52 +       brcmf_dbg(TRACE, "Enter, bssidx=%d\n", ifp->bsscfgidx);
53 +
54 +       memcpy(gtk_le.kck, gtk->kck, sizeof(gtk_le.kck));
55 +       memcpy(gtk_le.kek, gtk->kek, sizeof(gtk_le.kek));
56 +       memcpy(gtk_le.replay_counter, gtk->replay_ctr,
57 +              sizeof(gtk_le.replay_counter));
58 +
59 +       ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", &gtk_le,
60 +                                      sizeof(gtk_le));
61 +       if (ret < 0)
62 +               brcmf_err("gtk_key_info iovar failed: ret=%d\n", ret);
63 +
64 +       return ret;
65 +}
66 +#endif
67 +
68 +static struct cfg80211_ops brcmf_cfg80211_ops = {
69         .add_virtual_intf = brcmf_cfg80211_add_iface,
70         .del_virtual_intf = brcmf_cfg80211_del_iface,
71         .change_virtual_intf = brcmf_cfg80211_change_iface,
72 @@ -6139,19 +6170,18 @@ static void brcmf_wiphy_wowl_params(stru
73  {
74  #ifdef CONFIG_PM
75         struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
76 -       s32 err;
77 -       u32 wowl_cap;
78  
79         if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
80 -               err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
81 -               if (!err) {
82 -                       if (wowl_cap & BRCMF_WOWL_PFN_FOUND) {
83 -                               brcmf_wowlan_support.flags |=
84 -                                                       WIPHY_WOWLAN_NET_DETECT;
85 -                               init_waitqueue_head(&cfg->wowl.nd_data_wait);
86 -                       }
87 +               if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ND)) {
88 +                       brcmf_wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT;
89 +                       init_waitqueue_head(&cfg->wowl.nd_data_wait);
90                 }
91         }
92 +       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) {
93 +               brcmf_wowlan_support.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY;
94 +               brcmf_wowlan_support.flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE;
95 +       }
96 +
97         wiphy->wowlan = &brcmf_wowlan_support;
98  #endif
99  }
100 @@ -6538,6 +6568,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
101         struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
102         struct brcmf_cfg80211_info *cfg;
103         struct wiphy *wiphy;
104 +       struct cfg80211_ops *ops;
105         struct brcmf_cfg80211_vif *vif;
106         struct brcmf_if *ifp;
107         s32 err = 0;
108 @@ -6549,8 +6580,17 @@ struct brcmf_cfg80211_info *brcmf_cfg802
109                 return NULL;
110         }
111  
112 +       ops = kzalloc(sizeof(*ops), GFP_KERNEL);
113 +       if (!ops)
114 +               return NULL;
115 +
116 +       memcpy(ops, &brcmf_cfg80211_ops, sizeof(*ops));
117         ifp = netdev_priv(ndev);
118 -       wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
119 +#ifdef CONFIG_PM
120 +       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
121 +               ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
122 +#endif
123 +       wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info));
124         if (!wiphy) {
125                 brcmf_err("Could not allocate wiphy device\n");
126                 return NULL;
127 @@ -6560,6 +6600,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
128  
129         cfg = wiphy_priv(wiphy);
130         cfg->wiphy = wiphy;
131 +       cfg->ops = ops;
132         cfg->pub = drvr;
133         init_vif_event(&cfg->vif_event);
134         INIT_LIST_HEAD(&cfg->vif_list);
135 @@ -6686,6 +6727,7 @@ priv_out:
136         ifp->vif = NULL;
137  wiphy_out:
138         brcmf_free_wiphy(wiphy);
139 +       kfree(ops);
140         return NULL;
141  }
142  
143 @@ -6696,6 +6738,7 @@ void brcmf_cfg80211_detach(struct brcmf_
144  
145         brcmf_btcoex_detach(cfg);
146         wiphy_unregister(cfg->wiphy);
147 +       kfree(cfg->ops);
148         wl_deinit_priv(cfg);
149         brcmf_free_wiphy(cfg->wiphy);
150  }
151 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
152 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
153 @@ -256,6 +256,7 @@ struct brcmf_cfg80211_wowl {
154   * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
155   *
156   * @wiphy: wiphy object for cfg80211 interface.
157 + * @ops: pointer to copy of ops as registered with wiphy object.
158   * @conf: dongle configuration.
159   * @p2p: peer-to-peer specific information.
160   * @btcoex: Bluetooth coexistence information.
161 @@ -288,6 +289,7 @@ struct brcmf_cfg80211_wowl {
162   */
163  struct brcmf_cfg80211_info {
164         struct wiphy *wiphy;
165 +       struct cfg80211_ops *ops;
166         struct brcmf_cfg80211_conf *conf;
167         struct brcmf_p2p_info p2p;
168         struct brcmf_btcoex_info *btcoex;
169 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
170 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
171 @@ -136,6 +136,7 @@ void brcmf_feat_attach(struct brcmf_pub
172  {
173         struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
174         struct brcmf_pno_macaddr_le pfn_mac;
175 +       u32 wowl_cap;
176         s32 err;
177  
178         brcmf_feat_firmware_capabilities(ifp);
179 @@ -143,6 +144,17 @@ void brcmf_feat_attach(struct brcmf_pub
180         brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
181         if (drvr->bus_if->wowl_supported)
182                 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
183 +       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) {
184 +               err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
185 +               if (!err) {
186 +                       if (wowl_cap & BRCMF_WOWL_PFN_FOUND)
187 +                               ifp->drvr->feat_flags |=
188 +                                       BIT(BRCMF_FEAT_WOWL_ND);
189 +                       if (wowl_cap & BRCMF_WOWL_GTK_FAILURE)
190 +                               ifp->drvr->feat_flags |=
191 +                                       BIT(BRCMF_FEAT_WOWL_GTK);
192 +               }
193 +       }
194         /* MBSS does not work for 43362 */
195         if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID)
196                 ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS);
197 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
198 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
199 @@ -27,6 +27,8 @@
200   * RSDB: Real Simultaneous Dual Band
201   * TDLS: Tunneled Direct Link Setup
202   * SCAN_RANDOM_MAC: Random MAC during (net detect) scheduled scan.
203 + * WOWL_ND: WOWL net detect (PNO)
204 + * WOWL_GTK: (WOWL) GTK rekeying offload
205   */
206  #define BRCMF_FEAT_LIST \
207         BRCMF_FEAT_DEF(MBSS) \
208 @@ -36,7 +38,9 @@
209         BRCMF_FEAT_DEF(P2P) \
210         BRCMF_FEAT_DEF(RSDB) \
211         BRCMF_FEAT_DEF(TDLS) \
212 -       BRCMF_FEAT_DEF(SCAN_RANDOM_MAC)
213 +       BRCMF_FEAT_DEF(SCAN_RANDOM_MAC) \
214 +       BRCMF_FEAT_DEF(WOWL_ND) \
215 +       BRCMF_FEAT_DEF(WOWL_GTK)
216  
217  /*
218   * Quirks:
219 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
220 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
221 @@ -111,7 +111,9 @@
222  /* Wakeup if received matched secured pattern: */
223  #define BRCMF_WOWL_SECURE              (1 << 25)
224  /* Wakeup on finding preferred network */
225 -#define BRCMF_WOWL_PFN_FOUND           (1 << 26)
226 +#define BRCMF_WOWL_PFN_FOUND           (1 << 27)
227 +/* Wakeup on receiving pairwise key EAP packets: */
228 +#define WIPHY_WOWL_EAP_PK              (1 << 28)
229  /* Link Down indication in WoWL mode: */
230  #define BRCMF_WOWL_LINKDOWN            (1 << 31)
231  
232 @@ -136,6 +138,10 @@
233  
234  #define BRCMF_MCSSET_LEN               16
235  
236 +#define BRCMF_RSN_KCK_LENGTH           16
237 +#define BRCMF_RSN_KEK_LENGTH           16
238 +#define BRCMF_RSN_REPLAY_LEN           8
239 +
240  /* join preference types for join_pref iovar */
241  enum brcmf_join_pref_types {
242         BRCMF_JOIN_PREF_RSSI = 1,
243 @@ -789,4 +795,17 @@ struct brcmf_pktcnt_le {
244         __le32 rx_ocast_good_pkt;
245  };
246  
247 +/**
248 + * struct brcmf_gtk_keyinfo_le - GTP rekey data
249 + *
250 + * @kck: key confirmation key.
251 + * @kek: key encryption key.
252 + * @replay_counter: replay counter.
253 + */
254 +struct brcmf_gtk_keyinfo_le {
255 +       u8 kck[BRCMF_RSN_KCK_LENGTH];
256 +       u8 kek[BRCMF_RSN_KEK_LENGTH];
257 +       u8 replay_counter[BRCMF_RSN_REPLAY_LEN];
258 +};
259 +
260  #endif /* FWIL_TYPES_H_ */