--- /dev/null
+From 0542503c4c164c65cd1567b0f2b3f887af6c81eb Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Tue, 20 Feb 2018 00:14:22 +0100
+Subject: [PATCH] brcmfmac: move brcmf_attach() function in core.c
+
+Moving the function in preparation of subsequent patch.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../wireless/broadcom/brcm80211/brcmfmac/core.c | 98 +++++++++++-----------
+ 1 file changed, 49 insertions(+), 49 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -961,55 +961,6 @@ static int brcmf_inet6addr_changed(struc
+ }
+ #endif
+
+-int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
+-{
+- struct brcmf_pub *drvr = NULL;
+- int ret = 0;
+- int i;
+-
+- brcmf_dbg(TRACE, "Enter\n");
+-
+- /* Allocate primary brcmf_info */
+- drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
+- if (!drvr)
+- return -ENOMEM;
+-
+- for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
+- drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
+-
+- mutex_init(&drvr->proto_block);
+-
+- /* Link to bus module */
+- drvr->hdrlen = 0;
+- drvr->bus_if = dev_get_drvdata(dev);
+- drvr->bus_if->drvr = drvr;
+- drvr->settings = settings;
+-
+- /* attach debug facilities */
+- brcmf_debug_attach(drvr);
+-
+- /* Attach and link in the protocol */
+- ret = brcmf_proto_attach(drvr);
+- if (ret != 0) {
+- brcmf_err("brcmf_prot_attach failed\n");
+- goto fail;
+- }
+-
+- /* Attach to events important for core code */
+- brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG,
+- brcmf_psm_watchdog_notify);
+-
+- /* attach firmware event handler */
+- brcmf_fweh_attach(drvr);
+-
+- return ret;
+-
+-fail:
+- brcmf_detach(dev);
+-
+- return ret;
+-}
+-
+ static int brcmf_revinfo_read(struct seq_file *s, void *data)
+ {
+ struct brcmf_bus *bus_if = dev_get_drvdata(s->private);
+@@ -1141,6 +1092,55 @@ fail:
+
+ return ret;
+ }
++
++int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
++{
++ struct brcmf_pub *drvr = NULL;
++ int ret = 0;
++ int i;
++
++ brcmf_dbg(TRACE, "Enter\n");
++
++ /* Allocate primary brcmf_info */
++ drvr = kzalloc(sizeof(*drvr), GFP_ATOMIC);
++ if (!drvr)
++ return -ENOMEM;
++
++ for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
++ drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
++
++ mutex_init(&drvr->proto_block);
++
++ /* Link to bus module */
++ drvr->hdrlen = 0;
++ drvr->bus_if = dev_get_drvdata(dev);
++ drvr->bus_if->drvr = drvr;
++ drvr->settings = settings;
++
++ /* attach debug facilities */
++ brcmf_debug_attach(drvr);
++
++ /* Attach and link in the protocol */
++ ret = brcmf_proto_attach(drvr);
++ if (ret != 0) {
++ brcmf_err("brcmf_prot_attach failed\n");
++ goto fail;
++ }
++
++ /* Attach to events important for core code */
++ brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG,
++ brcmf_psm_watchdog_notify);
++
++ /* attach firmware event handler */
++ brcmf_fweh_attach(drvr);
++
++ return ret;
++
++fail:
++ brcmf_detach(dev);
++
++ return ret;
++}
+
+ void brcmf_bus_add_txhdrlen(struct device *dev, uint len)
+ {
--- /dev/null
+From 856d5a011c86b59f6564be4508912fb1d866adfc Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Thu, 22 Mar 2018 21:28:23 +0100
+Subject: [PATCH] brcmfmac: allocate struct brcmf_pub instance using
+ wiphy_new()
+
+Rework the driver so the wiphy instance holds the main driver information
+in its private buffer. Previously it held struct brcmf_cfg80211_info
+instance so a bit of reorg was needed. This was done so that the wiphy
+name or its parent device can be shown in debug output.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../wireless/broadcom/brcm80211/brcmfmac/btcoex.c | 2 +-
+ .../broadcom/brcm80211/brcmfmac/cfg80211.c | 86 ++++++++++------------
+ .../broadcom/brcm80211/brcmfmac/cfg80211.h | 17 +++--
+ .../wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +
+ .../wireless/broadcom/brcm80211/brcmfmac/core.c | 27 +++++--
+ .../wireless/broadcom/brcm80211/brcmfmac/core.h | 1 +
+ .../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 2 +-
+ 7 files changed, 76 insertions(+), 61 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
+@@ -464,7 +464,7 @@ static void brcmf_btcoex_dhcp_end(struct
+ int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
+ enum brcmf_btcoex_mode mode, u16 duration)
+ {
+- struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
++ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
+ struct brcmf_btcoex_info *btci = cfg->btcoex;
+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -783,7 +783,7 @@ s32 brcmf_notify_escan_complete(struct b
+ static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
+ {
+- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
++ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct net_device *ndev = wdev->netdev;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ int ret;
+@@ -816,7 +816,7 @@ err_unarm:
+ static
+ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
+ {
+- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
++ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct net_device *ndev = wdev->netdev;
+
+ if (ndev && ndev == cfg_to_ndev(cfg))
+@@ -861,7 +861,7 @@ brcmf_cfg80211_change_iface(struct wiphy
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+ {
+- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
++ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_vif *vif = ifp->vif;
+ s32 infra = 0;
+@@ -2175,17 +2175,15 @@ static s32
+ brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ s32 *dbm)
+ {
+- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+- struct net_device *ndev = cfg_to_ndev(cfg);
+- struct brcmf_if *ifp = netdev_priv(ndev);
++ struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev);
+ s32 qdbm = 0;
+ s32 err;
+
+ brcmf_dbg(TRACE, "Enter\n");
+- if (!check_vif_up(ifp->vif))
++ if (!check_vif_up(vif))
+ return -EIO;
+
+- err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &qdbm);
++ err = brcmf_fil_iovar_int_get(vif->ifp, "qtxpower", &qdbm);
+ if (err) {
+ brcmf_err("error (%d)\n", err);
+ goto done;
+@@ -3398,7 +3396,7 @@ brcmf_cfg80211_sched_scan_start(struct w
+ struct cfg80211_sched_scan_request *req)
+ {
+ struct brcmf_if *ifp = netdev_priv(ndev);
+- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
++ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+
+ brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
+ req->n_match_sets, req->n_ssids);
+@@ -5192,6 +5190,12 @@ static struct cfg80211_ops brcmf_cfg8021
+ .update_connect_params = brcmf_cfg80211_update_conn_params,
+ };
+
++struct cfg80211_ops *brcmf_cfg80211_get_ops(void)
++{
++ return kmemdup(&brcmf_cfg80211_ops, sizeof(brcmf_cfg80211_ops),
++ GFP_KERNEL);
++}
++
+ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
+ enum nl80211_iftype type)
+ {
+@@ -5866,7 +5870,7 @@ static void brcmf_update_bw40_channel_fl
+ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
+ u32 bw_cap[])
+ {
+- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
++ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+ struct ieee80211_supported_band *band;
+ struct ieee80211_channel *channel;
+ struct wiphy *wiphy;
+@@ -5981,7 +5985,7 @@ fail_pbuf:
+
+ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
+ {
+- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
++ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+ struct ieee80211_supported_band *band;
+ struct brcmf_fil_bwcap_le band_bwcap;
+ struct brcmf_chanspec_list *list;
+@@ -6166,10 +6170,10 @@ static void brcmf_update_vht_cap(struct
+ }
+ }
+
+-static int brcmf_setup_wiphybands(struct wiphy *wiphy)
++static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)
+ {
+- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
+- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
++ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
++ struct wiphy *wiphy;
+ u32 nmode = 0;
+ u32 vhtmode = 0;
+ u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
+@@ -6764,8 +6768,8 @@ static s32 brcmf_translate_country_code(
+ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
+ struct regulatory_request *req)
+ {
+- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
+- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
++ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
++ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+ struct brcmf_fil_country_le ccreq;
+ s32 err;
+ int i;
+@@ -6800,7 +6804,7 @@ static void brcmf_cfg80211_reg_notifier(
+ brcmf_err("Firmware rejected country setting\n");
+ return;
+ }
+- brcmf_setup_wiphybands(wiphy);
++ brcmf_setup_wiphybands(cfg);
+ }
+
+ static void brcmf_free_wiphy(struct wiphy *wiphy)
+@@ -6827,17 +6831,15 @@ static void brcmf_free_wiphy(struct wiph
+ if (wiphy->wowlan != &brcmf_wowlan_support)
+ kfree(wiphy->wowlan);
+ #endif
+- wiphy_free(wiphy);
+ }
+
+ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+- struct device *busdev,
++ struct cfg80211_ops *ops,
+ bool p2pdev_forced)
+ {
++ struct wiphy *wiphy = drvr->wiphy;
+ 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;
+@@ -6849,26 +6851,13 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ return NULL;
+ }
+
+- ops = kmemdup(&brcmf_cfg80211_ops, sizeof(*ops), GFP_KERNEL);
+- if (!ops)
+- return NULL;
+-
+- ifp = netdev_priv(ndev);
+-#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) {
++ cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
++ if (!cfg) {
+ brcmf_err("Could not allocate wiphy device\n");
+- goto ops_out;
++ return NULL;
+ }
+- memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
+- set_wiphy_dev(wiphy, busdev);
+
+- 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);
+@@ -6877,6 +6866,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ if (IS_ERR(vif))
+ goto wiphy_out;
+
++ ifp = netdev_priv(ndev);
+ vif->ifp = ifp;
+ vif->wdev.netdev = ndev;
+ ndev->ieee80211_ptr = &vif->wdev;
+@@ -6903,6 +6893,11 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ if (err < 0)
+ goto priv_out;
+
++ /* regulatory notifer below needs access to cfg so
++ * assign it now.
++ */
++ drvr->config = cfg;
++
+ brcmf_dbg(INFO, "Registering custom regulatory\n");
+ wiphy->reg_notifier = brcmf_cfg80211_reg_notifier;
+ wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
+@@ -6916,13 +6911,17 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap;
+ *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
++#ifdef CONFIG_PM
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
++ ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
++#endif
+ err = wiphy_register(wiphy);
+ if (err < 0) {
+ brcmf_err("Could not register wiphy device (%d)\n", err);
+ goto priv_out;
+ }
+
+- err = brcmf_setup_wiphybands(wiphy);
++ err = brcmf_setup_wiphybands(cfg);
+ if (err) {
+ brcmf_err("Setting wiphy bands failed (%d)\n", err);
+ goto wiphy_unreg_out;
+@@ -6939,12 +6938,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ else
+ *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
+- /* p2p might require that "if-events" get processed by fweh. So
+- * activate the already registered event handlers now and activate
+- * the rest when initialization has completed. drvr->config needs to
+- * be assigned before activating events.
+- */
+- drvr->config = cfg;
++
+ err = brcmf_fweh_activate_events(ifp);
+ if (err) {
+ brcmf_err("FWEH activation failed (%d)\n", err);
+@@ -7004,8 +6998,7 @@ priv_out:
+ ifp->vif = NULL;
+ wiphy_out:
+ brcmf_free_wiphy(wiphy);
+-ops_out:
+- kfree(ops);
++ kfree(cfg);
+ return NULL;
+ }
+
+@@ -7016,7 +7009,8 @@ void brcmf_cfg80211_detach(struct brcmf_
+
+ brcmf_btcoex_detach(cfg);
+ wiphy_unregister(cfg->wiphy);
+- kfree(cfg->ops);
++ kfree(cfg->pub->cfg80211_ops);
+ wl_deinit_priv(cfg);
+ brcmf_free_wiphy(cfg->wiphy);
++ kfree(cfg);
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -290,7 +290,7 @@ struct brcmf_cfg80211_wowl {
+ */
+ struct brcmf_cfg80211_info {
+ struct wiphy *wiphy;
+- struct cfg80211_ops *ops;
++// struct cfg80211_ops *ops; /* OpenWrt keeps it in the struct brcmf_pub */
+ struct brcmf_cfg80211_conf *conf;
+ struct brcmf_p2p_info p2p;
+ struct brcmf_btcoex_info *btcoex;
+@@ -342,20 +342,24 @@ static inline struct wiphy *cfg_to_wiphy
+
+ static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
+ {
+- return (struct brcmf_cfg80211_info *)(wiphy_priv(w));
++ struct brcmf_pub *drvr = wiphy_priv(w);
++ return drvr->config;
+ }
+
+ static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd)
+ {
+- return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
++ return wiphy_to_cfg(wd->wiphy);
++}
++
++static inline struct brcmf_cfg80211_vif *wdev_to_vif(struct wireless_dev *wdev)
++{
++ return container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+ }
+
+ static inline
+ struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
+ {
+- struct brcmf_cfg80211_vif *vif;
+- vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list);
+- return vif->wdev.netdev;
++ return brcmf_get_ifp(cfg->pub, 0)->ndev;
+ }
+
+ static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
+@@ -382,11 +386,12 @@ brcmf_cfg80211_connect_info *cfg_to_conn
+ }
+
+ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+- struct device *busdev,
++ struct cfg80211_ops *ops,
+ bool p2pdev_forced);
+ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
+ s32 brcmf_cfg80211_up(struct net_device *ndev);
+ s32 brcmf_cfg80211_down(struct net_device *ndev);
++struct cfg80211_ops *brcmf_cfg80211_get_ops(void);
+ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
+
+ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+@@ -124,6 +124,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
+ brcmf_err("Retreiving cur_etheraddr failed, %d\n", err);
+ goto done;
+ }
++ memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN);
+ memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
+
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO,
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1036,7 +1036,7 @@ int brcmf_bus_started(struct device *dev
+
+ brcmf_fws_add_interface(ifp);
+
+- drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev,
++ drvr->config = brcmf_cfg80211_attach(drvr, drvr->cfg80211_ops,
+ drvr->settings->p2p_enable);
+ if (drvr->config == NULL) {
+ ret = -ENOMEM;
+@@ -1095,17 +1095,26 @@ fail:
+
+ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
+ {
++ struct wiphy *wiphy;
++ struct cfg80211_ops *ops;
+ struct brcmf_pub *drvr = NULL;
+ int ret = 0;
+ int i;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+- /* Allocate primary brcmf_info */
+- drvr = kzalloc(sizeof(*drvr), GFP_ATOMIC);
+- if (!drvr)
++ ops = brcmf_cfg80211_get_ops();
++ if (!ops)
+ return -ENOMEM;
+
++ wiphy = wiphy_new(ops, sizeof(*drvr));
++ if (!wiphy)
++ return -ENOMEM;
++
++ set_wiphy_dev(wiphy, dev);
++ drvr = wiphy_priv(wiphy);
++ drvr->wiphy = wiphy;
++
+ for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
+ drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
+
+@@ -1134,10 +1143,12 @@ int brcmf_attach(struct device *dev, str
+ /* attach firmware event handler */
+ brcmf_fweh_attach(drvr);
+
++ drvr->cfg80211_ops = ops;
+ return ret;
+
+ fail:
+ brcmf_detach(dev);
++ kfree(ops);
+
+ return ret;
+ }
+@@ -1195,6 +1206,7 @@ void brcmf_detach(struct device *dev)
+ brcmf_remove_interface(drvr->iflist[i], false);
+
+ brcmf_cfg80211_detach(drvr->config);
++ drvr->config = NULL;
+
+ brcmf_fws_deinit(drvr);
+
+@@ -1204,7 +1216,7 @@ void brcmf_detach(struct device *dev)
+
+ brcmf_debug_detach(drvr);
+ bus_if->drvr = NULL;
+- kfree(drvr);
++ wiphy_free(drvr->wiphy);
+ }
+
+ s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len)
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -108,6 +108,7 @@ struct brcmf_pub {
+ /* Linkage ponters */
+ struct brcmf_bus *bus_if;
+ struct brcmf_proto *proto;
++ struct wiphy *wiphy;
+ struct brcmf_cfg80211_info *config;
+
+ /* Internal brcmf items */
+@@ -143,6 +144,9 @@ struct brcmf_pub {
+ struct notifier_block inetaddr_notifier;
+ struct notifier_block inet6addr_notifier;
+ struct brcmf_mp_device *settings;
++
++ /* Pointer needed by OpenWrt due to backporting some fixes */
++ void *cfg80211_ops;
+ };
+
+ /* forward declarations */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+@@ -2236,7 +2236,7 @@ fail:
+ */
+ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
+ {
+- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
++ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_p2p_info *p2p = &cfg->p2p;
+ struct brcmf_cfg80211_vif *vif;
+ enum nl80211_iftype iftype;