Skip to content

Commit 5c22fb8

Browse files
Hante MeulemanKalle Valo
authored andcommitted
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 <[email protected]> Reviewed-by: Franky (Zhenhui) Lin <[email protected]> Reviewed-by: Pieter-Paul Giesberts <[email protected]> Signed-off-by: Hante Meuleman <[email protected]> Signed-off-by: Arend van Spriel <[email protected]> Signed-off-by: Kalle Valo <[email protected]>
1 parent d84d99e commit 5c22fb8

File tree

5 files changed

+93
-13
lines changed

5 files changed

+93
-13
lines changed

drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3526,6 +3526,10 @@ static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
35263526
else
35273527
wakeup_data.net_detect = cfg->wowl.nd_info;
35283528
}
3529+
if (wakeind & BRCMF_WOWL_GTK_FAILURE) {
3530+
brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_GTK_FAILURE\n");
3531+
wakeup_data.gtk_rekey_failure = true;
3532+
}
35293533
} else {
35303534
wakeup = NULL;
35313535
}
@@ -3607,6 +3611,8 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg,
36073611
brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
36083612
brcmf_wowl_nd_results);
36093613
}
3614+
if (wowl->gtk_rekey_failure)
3615+
wowl_config |= BRCMF_WOWL_GTK_FAILURE;
36103616
if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
36113617
wowl_config |= BRCMF_WOWL_UNASSOC;
36123618

@@ -4874,7 +4880,32 @@ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
48744880
return ret;
48754881
}
48764882

4877-
static struct cfg80211_ops wl_cfg80211_ops = {
4883+
#ifdef CONFIG_PM
4884+
static int
4885+
brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
4886+
struct cfg80211_gtk_rekey_data *gtk)
4887+
{
4888+
struct brcmf_if *ifp = netdev_priv(ndev);
4889+
struct brcmf_gtk_keyinfo_le gtk_le;
4890+
int ret;
4891+
4892+
brcmf_dbg(TRACE, "Enter, bssidx=%d\n", ifp->bsscfgidx);
4893+
4894+
memcpy(gtk_le.kck, gtk->kck, sizeof(gtk_le.kck));
4895+
memcpy(gtk_le.kek, gtk->kek, sizeof(gtk_le.kek));
4896+
memcpy(gtk_le.replay_counter, gtk->replay_ctr,
4897+
sizeof(gtk_le.replay_counter));
4898+
4899+
ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", &gtk_le,
4900+
sizeof(gtk_le));
4901+
if (ret < 0)
4902+
brcmf_err("gtk_key_info iovar failed: ret=%d\n", ret);
4903+
4904+
return ret;
4905+
}
4906+
#endif
4907+
4908+
static struct cfg80211_ops brcmf_cfg80211_ops = {
48784909
.add_virtual_intf = brcmf_cfg80211_add_iface,
48794910
.del_virtual_intf = brcmf_cfg80211_del_iface,
48804911
.change_virtual_intf = brcmf_cfg80211_change_iface,
@@ -6139,19 +6170,18 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp)
61396170
{
61406171
#ifdef CONFIG_PM
61416172
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
6142-
s32 err;
6143-
u32 wowl_cap;
61446173

61456174
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
6146-
err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
6147-
if (!err) {
6148-
if (wowl_cap & BRCMF_WOWL_PFN_FOUND) {
6149-
brcmf_wowlan_support.flags |=
6150-
WIPHY_WOWLAN_NET_DETECT;
6151-
init_waitqueue_head(&cfg->wowl.nd_data_wait);
6152-
}
6175+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ND)) {
6176+
brcmf_wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT;
6177+
init_waitqueue_head(&cfg->wowl.nd_data_wait);
61536178
}
61546179
}
6180+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) {
6181+
brcmf_wowlan_support.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY;
6182+
brcmf_wowlan_support.flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE;
6183+
}
6184+
61556185
wiphy->wowlan = &brcmf_wowlan_support;
61566186
#endif
61576187
}
@@ -6538,6 +6568,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
65386568
struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
65396569
struct brcmf_cfg80211_info *cfg;
65406570
struct wiphy *wiphy;
6571+
struct cfg80211_ops *ops;
65416572
struct brcmf_cfg80211_vif *vif;
65426573
struct brcmf_if *ifp;
65436574
s32 err = 0;
@@ -6549,8 +6580,17 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
65496580
return NULL;
65506581
}
65516582

6583+
ops = kzalloc(sizeof(*ops), GFP_KERNEL);
6584+
if (!ops)
6585+
return NULL;
6586+
6587+
memcpy(ops, &brcmf_cfg80211_ops, sizeof(*ops));
65526588
ifp = netdev_priv(ndev);
6553-
wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
6589+
#ifdef CONFIG_PM
6590+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
6591+
ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
6592+
#endif
6593+
wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info));
65546594
if (!wiphy) {
65556595
brcmf_err("Could not allocate wiphy device\n");
65566596
return NULL;
@@ -6560,6 +6600,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
65606600

65616601
cfg = wiphy_priv(wiphy);
65626602
cfg->wiphy = wiphy;
6603+
cfg->ops = ops;
65636604
cfg->pub = drvr;
65646605
init_vif_event(&cfg->vif_event);
65656606
INIT_LIST_HEAD(&cfg->vif_list);
@@ -6686,6 +6727,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
66866727
ifp->vif = NULL;
66876728
wiphy_out:
66886729
brcmf_free_wiphy(wiphy);
6730+
kfree(ops);
66896731
return NULL;
66906732
}
66916733

@@ -6696,6 +6738,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
66966738

66976739
brcmf_btcoex_detach(cfg);
66986740
wiphy_unregister(cfg->wiphy);
6741+
kfree(cfg->ops);
66996742
wl_deinit_priv(cfg);
67006743
brcmf_free_wiphy(cfg->wiphy);
67016744
}

drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ struct brcmf_cfg80211_wowl {
256256
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
257257
*
258258
* @wiphy: wiphy object for cfg80211 interface.
259+
* @ops: pointer to copy of ops as registered with wiphy object.
259260
* @conf: dongle configuration.
260261
* @p2p: peer-to-peer specific information.
261262
* @btcoex: Bluetooth coexistence information.
@@ -288,6 +289,7 @@ struct brcmf_cfg80211_wowl {
288289
*/
289290
struct brcmf_cfg80211_info {
290291
struct wiphy *wiphy;
292+
struct cfg80211_ops *ops;
291293
struct brcmf_cfg80211_conf *conf;
292294
struct brcmf_p2p_info p2p;
293295
struct brcmf_btcoex_info *btcoex;

drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,25 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
136136
{
137137
struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
138138
struct brcmf_pno_macaddr_le pfn_mac;
139+
u32 wowl_cap;
139140
s32 err;
140141

141142
brcmf_feat_firmware_capabilities(ifp);
142143

143144
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
144145
if (drvr->bus_if->wowl_supported)
145146
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
147+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) {
148+
err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
149+
if (!err) {
150+
if (wowl_cap & BRCMF_WOWL_PFN_FOUND)
151+
ifp->drvr->feat_flags |=
152+
BIT(BRCMF_FEAT_WOWL_ND);
153+
if (wowl_cap & BRCMF_WOWL_GTK_FAILURE)
154+
ifp->drvr->feat_flags |=
155+
BIT(BRCMF_FEAT_WOWL_GTK);
156+
}
157+
}
146158
/* MBSS does not work for 43362 */
147159
if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID)
148160
ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS);

drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
* RSDB: Real Simultaneous Dual Band
2828
* TDLS: Tunneled Direct Link Setup
2929
* SCAN_RANDOM_MAC: Random MAC during (net detect) scheduled scan.
30+
* WOWL_ND: WOWL net detect (PNO)
31+
* WOWL_GTK: (WOWL) GTK rekeying offload
3032
*/
3133
#define BRCMF_FEAT_LIST \
3234
BRCMF_FEAT_DEF(MBSS) \
@@ -36,7 +38,9 @@
3638
BRCMF_FEAT_DEF(P2P) \
3739
BRCMF_FEAT_DEF(RSDB) \
3840
BRCMF_FEAT_DEF(TDLS) \
39-
BRCMF_FEAT_DEF(SCAN_RANDOM_MAC)
41+
BRCMF_FEAT_DEF(SCAN_RANDOM_MAC) \
42+
BRCMF_FEAT_DEF(WOWL_ND) \
43+
BRCMF_FEAT_DEF(WOWL_GTK)
4044

4145
/*
4246
* Quirks:

drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@
111111
/* Wakeup if received matched secured pattern: */
112112
#define BRCMF_WOWL_SECURE (1 << 25)
113113
/* Wakeup on finding preferred network */
114-
#define BRCMF_WOWL_PFN_FOUND (1 << 26)
114+
#define BRCMF_WOWL_PFN_FOUND (1 << 27)
115+
/* Wakeup on receiving pairwise key EAP packets: */
116+
#define WIPHY_WOWL_EAP_PK (1 << 28)
115117
/* Link Down indication in WoWL mode: */
116118
#define BRCMF_WOWL_LINKDOWN (1 << 31)
117119

@@ -136,6 +138,10 @@
136138

137139
#define BRCMF_MCSSET_LEN 16
138140

141+
#define BRCMF_RSN_KCK_LENGTH 16
142+
#define BRCMF_RSN_KEK_LENGTH 16
143+
#define BRCMF_RSN_REPLAY_LEN 8
144+
139145
/* join preference types for join_pref iovar */
140146
enum brcmf_join_pref_types {
141147
BRCMF_JOIN_PREF_RSSI = 1,
@@ -789,4 +795,17 @@ struct brcmf_pktcnt_le {
789795
__le32 rx_ocast_good_pkt;
790796
};
791797

798+
/**
799+
* struct brcmf_gtk_keyinfo_le - GTP rekey data
800+
*
801+
* @kck: key confirmation key.
802+
* @kek: key encryption key.
803+
* @replay_counter: replay counter.
804+
*/
805+
struct brcmf_gtk_keyinfo_le {
806+
u8 kck[BRCMF_RSN_KCK_LENGTH];
807+
u8 kek[BRCMF_RSN_KEK_LENGTH];
808+
u8 replay_counter[BRCMF_RSN_REPLAY_LEN];
809+
};
810+
792811
#endif /* FWIL_TYPES_H_ */

0 commit comments

Comments
 (0)