Commit cbb371da authored by Arend van Spriel's avatar Arend van Spriel Committed by John W. Linville

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: default avatarHante Meuleman <meuleman@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 9390ace9
...@@ -653,6 +653,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) ...@@ -653,6 +653,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
ndev->destructor = free_netdev;
return 0; return 0;
fail: fail:
...@@ -793,6 +794,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) ...@@ -793,6 +794,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
struct brcmf_if *ifp; struct brcmf_if *ifp;
ifp = drvr->iflist[bssidx]; ifp = drvr->iflist[bssidx];
drvr->iflist[bssidx] = NULL;
if (!ifp) { if (!ifp) {
brcmf_err("Null interface, idx=%d\n", bssidx); brcmf_err("Null interface, idx=%d\n", bssidx);
return; return;
...@@ -813,15 +815,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) ...@@ -813,15 +815,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
cancel_work_sync(&ifp->setmacaddr_work); cancel_work_sync(&ifp->setmacaddr_work);
cancel_work_sync(&ifp->multicast_work); cancel_work_sync(&ifp->multicast_work);
} }
/* unregister will take care of freeing it */
unregister_netdev(ifp->ndev); unregister_netdev(ifp->ndev);
if (bssidx == 0) if (bssidx == 0)
brcmf_cfg80211_detach(drvr->config); brcmf_cfg80211_detach(drvr->config);
free_netdev(ifp->ndev);
} else { } else {
kfree(ifp); kfree(ifp);
} }
drvr->iflist[bssidx] = NULL;
} }
int brcmf_attach(uint bus_hdrlen, struct device *dev) int brcmf_attach(uint bus_hdrlen, struct device *dev)
......
...@@ -2239,6 +2239,25 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_info *cfg, ...@@ -2239,6 +2239,25 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_info *cfg,
brcmf_free_vif(cfg, vif); brcmf_free_vif(cfg, vif);
} }
/**
* brcmf_p2p_free_p2p_if() - free up net device related data.
*
* @ndev: net device that needs to be freed.
*/
static void brcmf_p2p_free_p2p_if(struct net_device *ndev)
{
struct brcmf_cfg80211_info *cfg;
struct brcmf_cfg80211_vif *vif;
struct brcmf_if *ifp;
ifp = netdev_priv(ndev);
cfg = ifp->drvr->config;
vif = ifp->vif;
brcmf_free_vif(cfg, vif);
free_netdev(ifp->ndev);
}
/** /**
* brcmf_p2p_add_vif() - create a new P2P virtual interface. * brcmf_p2p_add_vif() - create a new P2P virtual interface.
* *
...@@ -2316,6 +2335,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, ...@@ -2316,6 +2335,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
brcmf_err("Registering netdevice failed\n"); brcmf_err("Registering netdevice failed\n");
goto fail; goto fail;
} }
/* override destructor */
ifp->ndev->destructor = brcmf_p2p_free_p2p_if;
cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif; cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif;
/* Disable firmware roaming for P2P interface */ /* Disable firmware roaming for P2P interface */
brcmf_fil_iovar_int_set(ifp, "roam_off", 1); 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,7 +2413,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
err = 0; err = 0;
} }
brcmf_cfg80211_arm_vif_event(cfg, NULL); brcmf_cfg80211_arm_vif_event(cfg, NULL);
brcmf_free_vif(cfg, vif);
p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
return err; return err;
......
...@@ -4678,7 +4678,6 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp, ...@@ -4678,7 +4678,6 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
return 0; return 0;
case BRCMF_E_IF_DEL: case BRCMF_E_IF_DEL:
ifp->vif = NULL;
mutex_unlock(&event->vif_event_lock); mutex_unlock(&event->vif_event_lock);
/* event may not be upon user request */ /* event may not be upon user request */
if (brcmf_cfg80211_vif_event_armed(cfg)) if (brcmf_cfg80211_vif_event_armed(cfg))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment