123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- 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", >k_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_ */
|