Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Arend van Spriel and committed by
John W. Linville
cbb371da 9390ace9

+25 -5
+3 -3
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
··· 653 653 654 654 brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); 655 655 656 + ndev->destructor = free_netdev; 656 657 return 0; 657 658 658 659 fail: ··· 794 793 struct brcmf_if *ifp; 795 794 796 795 ifp = drvr->iflist[bssidx]; 796 + drvr->iflist[bssidx] = NULL; 797 797 if (!ifp) { 798 798 brcmf_err("Null interface, idx=%d\n", bssidx); 799 799 return; ··· 815 813 cancel_work_sync(&ifp->setmacaddr_work); 816 814 cancel_work_sync(&ifp->multicast_work); 817 815 } 818 - 816 + /* unregister will take care of freeing it */ 819 817 unregister_netdev(ifp->ndev); 820 818 if (bssidx == 0) 821 819 brcmf_cfg80211_detach(drvr->config); 822 - free_netdev(ifp->ndev); 823 820 } else { 824 821 kfree(ifp); 825 822 } 826 - drvr->iflist[bssidx] = NULL; 827 823 } 828 824 829 825 int brcmf_attach(uint bus_hdrlen, struct device *dev)
+22 -1
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
··· 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 2262 * brcmf_p2p_add_vif() - create a new P2P virtual interface. 2244 2263 * 2245 2264 * @wiphy: wiphy device of new interface. ··· 2335 2316 brcmf_err("Registering netdevice failed\n"); 2336 2317 goto fail; 2337 2318 } 2319 + /* override destructor */ 2320 + ifp->ndev->destructor = brcmf_p2p_free_p2p_if; 2321 + 2338 2322 cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif; 2339 2323 /* Disable firmware roaming for P2P interface */ 2340 2324 brcmf_fil_iovar_int_set(ifp, "roam_off", 1); ··· 2413 2391 err = 0; 2414 2392 } 2415 2393 brcmf_cfg80211_arm_vif_event(cfg, NULL); 2416 - brcmf_free_vif(cfg, vif); 2417 2394 p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; 2418 2395 2419 2396 return err;
-1
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
··· 4678 4678 return 0; 4679 4679 4680 4680 case BRCMF_E_IF_DEL: 4681 - ifp->vif = NULL; 4682 4681 mutex_unlock(&event->vif_event_lock); 4683 4682 /* event may not be upon user request */ 4684 4683 if (brcmf_cfg80211_vif_event_armed(cfg))