diff options
author | Arend van Spriel <arend@broadcom.com> | 2013-05-27 15:09:57 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-05-28 13:43:09 -0400 |
commit | cbb371da233eb2b4c200010a5372579b880b4ae6 (patch) | |
tree | 11941df709d5c888ab9f90fcb9599557e9f7a61d /drivers/net | |
parent | 9390ace916b2fd866c1762b1cd16c276d8c8c890 (diff) |
brcmfmac: use struct net_device::destructor to remove interfaces
Upon deleting a P2P_CLIENT/GO interface the vif and consequently
the wdev is freed before the net_device is actually being unregistered
but cfg80211 still needs to access the wdev. Using destructor field
to free the net_device and vif.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 1 |
3 files changed, 25 insertions, 5 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index f04e3555dca3..b98f2235978e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -653,6 +653,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) | |||
653 | 653 | ||
654 | brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); | 654 | brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); |
655 | 655 | ||
656 | ndev->destructor = free_netdev; | ||
656 | return 0; | 657 | return 0; |
657 | 658 | ||
658 | fail: | 659 | fail: |
@@ -793,6 +794,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) | |||
793 | struct brcmf_if *ifp; | 794 | struct brcmf_if *ifp; |
794 | 795 | ||
795 | ifp = drvr->iflist[bssidx]; | 796 | ifp = drvr->iflist[bssidx]; |
797 | drvr->iflist[bssidx] = NULL; | ||
796 | if (!ifp) { | 798 | if (!ifp) { |
797 | brcmf_err("Null interface, idx=%d\n", bssidx); | 799 | brcmf_err("Null interface, idx=%d\n", bssidx); |
798 | return; | 800 | return; |
@@ -813,15 +815,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) | |||
813 | cancel_work_sync(&ifp->setmacaddr_work); | 815 | cancel_work_sync(&ifp->setmacaddr_work); |
814 | cancel_work_sync(&ifp->multicast_work); | 816 | cancel_work_sync(&ifp->multicast_work); |
815 | } | 817 | } |
816 | 818 | /* unregister will take care of freeing it */ | |
817 | unregister_netdev(ifp->ndev); | 819 | unregister_netdev(ifp->ndev); |
818 | if (bssidx == 0) | 820 | if (bssidx == 0) |
819 | brcmf_cfg80211_detach(drvr->config); | 821 | brcmf_cfg80211_detach(drvr->config); |
820 | free_netdev(ifp->ndev); | ||
821 | } else { | 822 | } else { |
822 | kfree(ifp); | 823 | kfree(ifp); |
823 | } | 824 | } |
824 | drvr->iflist[bssidx] = NULL; | ||
825 | } | 825 | } |
826 | 826 | ||
827 | int brcmf_attach(uint bus_hdrlen, struct device *dev) | 827 | int brcmf_attach(uint bus_hdrlen, struct device *dev) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 167b7afdf0d8..79555f006d53 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -2240,6 +2240,25 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_info *cfg, | |||
2240 | } | 2240 | } |
2241 | 2241 | ||
2242 | /** | 2242 | /** |
2243 | * brcmf_p2p_free_p2p_if() - free up net device related data. | ||
2244 | * | ||
2245 | * @ndev: net device that needs to be freed. | ||
2246 | */ | ||
2247 | static void brcmf_p2p_free_p2p_if(struct net_device *ndev) | ||
2248 | { | ||
2249 | struct brcmf_cfg80211_info *cfg; | ||
2250 | struct brcmf_cfg80211_vif *vif; | ||
2251 | struct brcmf_if *ifp; | ||
2252 | |||
2253 | ifp = netdev_priv(ndev); | ||
2254 | cfg = ifp->drvr->config; | ||
2255 | vif = ifp->vif; | ||
2256 | |||
2257 | brcmf_free_vif(cfg, vif); | ||
2258 | free_netdev(ifp->ndev); | ||
2259 | } | ||
2260 | |||
2261 | /** | ||
2243 | * brcmf_p2p_add_vif() - create a new P2P virtual interface. | 2262 | * brcmf_p2p_add_vif() - create a new P2P virtual interface. |
2244 | * | 2263 | * |
2245 | * @wiphy: wiphy device of new interface. | 2264 | * @wiphy: wiphy device of new interface. |
@@ -2316,6 +2335,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | |||
2316 | brcmf_err("Registering netdevice failed\n"); | 2335 | brcmf_err("Registering netdevice failed\n"); |
2317 | goto fail; | 2336 | goto fail; |
2318 | } | 2337 | } |
2338 | /* override destructor */ | ||
2339 | ifp->ndev->destructor = brcmf_p2p_free_p2p_if; | ||
2340 | |||
2319 | cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif; | 2341 | cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif; |
2320 | /* Disable firmware roaming for P2P interface */ | 2342 | /* Disable firmware roaming for P2P interface */ |
2321 | brcmf_fil_iovar_int_set(ifp, "roam_off", 1); | 2343 | brcmf_fil_iovar_int_set(ifp, "roam_off", 1); |
@@ -2391,7 +2413,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2391 | err = 0; | 2413 | err = 0; |
2392 | } | 2414 | } |
2393 | brcmf_cfg80211_arm_vif_event(cfg, NULL); | 2415 | brcmf_cfg80211_arm_vif_event(cfg, NULL); |
2394 | brcmf_free_vif(cfg, vif); | ||
2395 | p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; | 2416 | p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; |
2396 | 2417 | ||
2397 | return err; | 2418 | return err; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index f8c86b58a6d1..656ce8765863 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -4678,7 +4678,6 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp, | |||
4678 | return 0; | 4678 | return 0; |
4679 | 4679 | ||
4680 | case BRCMF_E_IF_DEL: | 4680 | case BRCMF_E_IF_DEL: |
4681 | ifp->vif = NULL; | ||
4682 | mutex_unlock(&event->vif_event_lock); | 4681 | mutex_unlock(&event->vif_event_lock); |
4683 | /* event may not be upon user request */ | 4682 | /* event may not be upon user request */ |
4684 | if (brcmf_cfg80211_vif_event_armed(cfg)) | 4683 | if (brcmf_cfg80211_vif_event_armed(cfg)) |