344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch 8.2 KB

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