summaryrefslogtreecommitdiff
path: root/package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch')
-rw-r--r--package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch260
1 files changed, 260 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch b/package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch
new file mode 100644
index 0000000..577ca8e
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch
@@ -0,0 +1,260 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:03 +0100
+Subject: [PATCH] brcmfmac: add wowl gtk rekeying offload support
+
+This patch adds support for gtk rekeying offload and for gtk
+rekeying failure during wowl mode.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -3526,6 +3526,10 @@ static void brcmf_report_wowl_wakeind(st
+ else
+ wakeup_data.net_detect = cfg->wowl.nd_info;
+ }
++ if (wakeind & BRCMF_WOWL_GTK_FAILURE) {
++ brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_GTK_FAILURE\n");
++ wakeup_data.gtk_rekey_failure = true;
++ }
+ } else {
+ wakeup = NULL;
+ }
+@@ -3607,6 +3611,8 @@ static void brcmf_configure_wowl(struct
+ brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
+ brcmf_wowl_nd_results);
+ }
++ if (wowl->gtk_rekey_failure)
++ wowl_config |= BRCMF_WOWL_GTK_FAILURE;
+ if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
+ wowl_config |= BRCMF_WOWL_UNASSOC;
+
+@@ -4874,7 +4880,32 @@ static int brcmf_cfg80211_tdls_oper(stru
+ return ret;
+ }
+
+-static struct cfg80211_ops wl_cfg80211_ops = {
++#ifdef CONFIG_PM
++static int
++brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
++ struct cfg80211_gtk_rekey_data *gtk)
++{
++ struct brcmf_if *ifp = netdev_priv(ndev);
++ struct brcmf_gtk_keyinfo_le gtk_le;
++ int ret;
++
++ brcmf_dbg(TRACE, "Enter, bssidx=%d\n", ifp->bsscfgidx);
++
++ memcpy(gtk_le.kck, gtk->kck, sizeof(gtk_le.kck));
++ memcpy(gtk_le.kek, gtk->kek, sizeof(gtk_le.kek));
++ memcpy(gtk_le.replay_counter, gtk->replay_ctr,
++ sizeof(gtk_le.replay_counter));
++
++ ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", &gtk_le,
++ sizeof(gtk_le));
++ if (ret < 0)
++ brcmf_err("gtk_key_info iovar failed: ret=%d\n", ret);
++
++ return ret;
++}
++#endif
++
++static struct cfg80211_ops brcmf_cfg80211_ops = {
+ .add_virtual_intf = brcmf_cfg80211_add_iface,
+ .del_virtual_intf = brcmf_cfg80211_del_iface,
+ .change_virtual_intf = brcmf_cfg80211_change_iface,
+@@ -6139,19 +6170,18 @@ static void brcmf_wiphy_wowl_params(stru
+ {
+ #ifdef CONFIG_PM
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+- s32 err;
+- u32 wowl_cap;
+
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
+- err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
+- if (!err) {
+- if (wowl_cap & BRCMF_WOWL_PFN_FOUND) {
+- brcmf_wowlan_support.flags |=
+- WIPHY_WOWLAN_NET_DETECT;
+- init_waitqueue_head(&cfg->wowl.nd_data_wait);
+- }
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ND)) {
++ brcmf_wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT;
++ init_waitqueue_head(&cfg->wowl.nd_data_wait);
+ }
+ }
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) {
++ brcmf_wowlan_support.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY;
++ brcmf_wowlan_support.flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE;
++ }
++
+ wiphy->wowlan = &brcmf_wowlan_support;
+ #endif
+ }
+@@ -6538,6 +6568,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
+ struct brcmf_cfg80211_info *cfg;
+ struct wiphy *wiphy;
++ struct cfg80211_ops *ops;
+ struct brcmf_cfg80211_vif *vif;
+ struct brcmf_if *ifp;
+ s32 err = 0;
+@@ -6549,8 +6580,17 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ return NULL;
+ }
+
++ ops = kzalloc(sizeof(*ops), GFP_KERNEL);
++ if (!ops)
++ return NULL;
++
++ memcpy(ops, &brcmf_cfg80211_ops, sizeof(*ops));
+ ifp = netdev_priv(ndev);
+- wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
++#ifdef CONFIG_PM
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
++ ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
++#endif
++ wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info));
+ if (!wiphy) {
+ brcmf_err("Could not allocate wiphy device\n");
+ return NULL;
+@@ -6560,6 +6600,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+
+ cfg = wiphy_priv(wiphy);
+ cfg->wiphy = wiphy;
++ cfg->ops = ops;
+ cfg->pub = drvr;
+ init_vif_event(&cfg->vif_event);
+ INIT_LIST_HEAD(&cfg->vif_list);
+@@ -6686,6 +6727,7 @@ priv_out:
+ ifp->vif = NULL;
+ wiphy_out:
+ brcmf_free_wiphy(wiphy);
++ kfree(ops);
+ return NULL;
+ }
+
+@@ -6696,6 +6738,7 @@ void brcmf_cfg80211_detach(struct brcmf_
+
+ brcmf_btcoex_detach(cfg);
+ wiphy_unregister(cfg->wiphy);
++ kfree(cfg->ops);
+ wl_deinit_priv(cfg);
+ brcmf_free_wiphy(cfg->wiphy);
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -256,6 +256,7 @@ struct brcmf_cfg80211_wowl {
+ * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
+ *
+ * @wiphy: wiphy object for cfg80211 interface.
++ * @ops: pointer to copy of ops as registered with wiphy object.
+ * @conf: dongle configuration.
+ * @p2p: peer-to-peer specific information.
+ * @btcoex: Bluetooth coexistence information.
+@@ -288,6 +289,7 @@ struct brcmf_cfg80211_wowl {
+ */
+ struct brcmf_cfg80211_info {
+ struct wiphy *wiphy;
++ struct cfg80211_ops *ops;
+ struct brcmf_cfg80211_conf *conf;
+ struct brcmf_p2p_info p2p;
+ struct brcmf_btcoex_info *btcoex;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+@@ -136,6 +136,7 @@ void brcmf_feat_attach(struct brcmf_pub
+ {
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
+ struct brcmf_pno_macaddr_le pfn_mac;
++ u32 wowl_cap;
+ s32 err;
+
+ brcmf_feat_firmware_capabilities(ifp);
+@@ -143,6 +144,17 @@ void brcmf_feat_attach(struct brcmf_pub
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
+ if (drvr->bus_if->wowl_supported)
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) {
++ err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
++ if (!err) {
++ if (wowl_cap & BRCMF_WOWL_PFN_FOUND)
++ ifp->drvr->feat_flags |=
++ BIT(BRCMF_FEAT_WOWL_ND);
++ if (wowl_cap & BRCMF_WOWL_GTK_FAILURE)
++ ifp->drvr->feat_flags |=
++ BIT(BRCMF_FEAT_WOWL_GTK);
++ }
++ }
+ /* MBSS does not work for 43362 */
+ if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID)
+ ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+@@ -27,6 +27,8 @@
+ * RSDB: Real Simultaneous Dual Band
+ * TDLS: Tunneled Direct Link Setup
+ * SCAN_RANDOM_MAC: Random MAC during (net detect) scheduled scan.
++ * WOWL_ND: WOWL net detect (PNO)
++ * WOWL_GTK: (WOWL) GTK rekeying offload
+ */
+ #define BRCMF_FEAT_LIST \
+ BRCMF_FEAT_DEF(MBSS) \
+@@ -36,7 +38,9 @@
+ BRCMF_FEAT_DEF(P2P) \
+ BRCMF_FEAT_DEF(RSDB) \
+ BRCMF_FEAT_DEF(TDLS) \
+- BRCMF_FEAT_DEF(SCAN_RANDOM_MAC)
++ BRCMF_FEAT_DEF(SCAN_RANDOM_MAC) \
++ BRCMF_FEAT_DEF(WOWL_ND) \
++ BRCMF_FEAT_DEF(WOWL_GTK)
+
+ /*
+ * Quirks:
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+@@ -111,7 +111,9 @@
+ /* Wakeup if received matched secured pattern: */
+ #define BRCMF_WOWL_SECURE (1 << 25)
+ /* Wakeup on finding preferred network */
+-#define BRCMF_WOWL_PFN_FOUND (1 << 26)
++#define BRCMF_WOWL_PFN_FOUND (1 << 27)
++/* Wakeup on receiving pairwise key EAP packets: */
++#define WIPHY_WOWL_EAP_PK (1 << 28)
+ /* Link Down indication in WoWL mode: */
+ #define BRCMF_WOWL_LINKDOWN (1 << 31)
+
+@@ -136,6 +138,10 @@
+
+ #define BRCMF_MCSSET_LEN 16
+
++#define BRCMF_RSN_KCK_LENGTH 16
++#define BRCMF_RSN_KEK_LENGTH 16
++#define BRCMF_RSN_REPLAY_LEN 8
++
+ /* join preference types for join_pref iovar */
+ enum brcmf_join_pref_types {
+ BRCMF_JOIN_PREF_RSSI = 1,
+@@ -789,4 +795,17 @@ struct brcmf_pktcnt_le {
+ __le32 rx_ocast_good_pkt;
+ };
+
++/**
++ * struct brcmf_gtk_keyinfo_le - GTP rekey data
++ *
++ * @kck: key confirmation key.
++ * @kek: key encryption key.
++ * @replay_counter: replay counter.
++ */
++struct brcmf_gtk_keyinfo_le {
++ u8 kck[BRCMF_RSN_KCK_LENGTH];
++ u8 kek[BRCMF_RSN_KEK_LENGTH];
++ u8 replay_counter[BRCMF_RSN_REPLAY_LEN];
++};
++
+ #endif /* FWIL_TYPES_H_ */