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>
This commit is contained in:
Родитель
9390ace916
Коммит
cbb371da23
|
@ -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);
|
||||
|
||||
ndev->destructor = free_netdev;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
@ -793,6 +794,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
|||
struct brcmf_if *ifp;
|
||||
|
||||
ifp = drvr->iflist[bssidx];
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
if (!ifp) {
|
||||
brcmf_err("Null interface, idx=%d\n", bssidx);
|
||||
return;
|
||||
|
@ -813,15 +815,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
|||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
}
|
||||
|
||||
/* unregister will take care of freeing it */
|
||||
unregister_netdev(ifp->ndev);
|
||||
if (bssidx == 0)
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
free_netdev(ifp->ndev);
|
||||
} else {
|
||||
kfree(ifp);
|
||||
}
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
}
|
||||
|
||||
int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
||||
|
|
|
@ -2239,6 +2239,25 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_info *cfg,
|
|||
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.
|
||||
*
|
||||
|
@ -2316,6 +2335,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
|
|||
brcmf_err("Registering netdevice failed\n");
|
||||
goto fail;
|
||||
}
|
||||
/* override destructor */
|
||||
ifp->ndev->destructor = brcmf_p2p_free_p2p_if;
|
||||
|
||||
cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif;
|
||||
/* Disable firmware roaming for P2P interface */
|
||||
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)
|
|||
err = 0;
|
||||
}
|
||||
brcmf_cfg80211_arm_vif_event(cfg, NULL);
|
||||
brcmf_free_vif(cfg, vif);
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
|
||||
|
||||
return err;
|
||||
|
|
|
@ -4678,7 +4678,6 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
|
|||
return 0;
|
||||
|
||||
case BRCMF_E_IF_DEL:
|
||||
ifp->vif = NULL;
|
||||
mutex_unlock(&event->vif_event_lock);
|
||||
/* event may not be upon user request */
|
||||
if (brcmf_cfg80211_vif_event_armed(cfg))
|
||||
|
|
Загрузка…
Ссылка в новой задаче