mirror of https://gitee.com/openkylin/linux.git
brcmfmac: wait for firmware event when creating P2P_DEVICE interface
The firmware sends a IF event to notify the host driver that the P2P_DEVICE interface has been created. Wait for the event before returning the related wireless_dev. Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Piotr Haber <phaber@broadcom.com> 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:
parent
27f10e380a
commit
01b8e7db61
|
@ -755,8 +755,14 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!brcmf_p2p_enable && bssidx == 1) {
|
||||||
|
/* this is P2P_DEVICE interface */
|
||||||
|
brcmf_dbg(INFO, "allocate non-netdev interface\n");
|
||||||
|
ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
|
||||||
|
} else {
|
||||||
|
brcmf_dbg(INFO, "allocate netdev interface\n");
|
||||||
/* Allocate netdev, including space for private structure */
|
/* Allocate netdev, including space for private structure */
|
||||||
ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
|
ndev = alloc_netdev(sizeof(*ifp), name, ether_setup);
|
||||||
if (!ndev) {
|
if (!ndev) {
|
||||||
brcmf_err("OOM - alloc_netdev\n");
|
brcmf_err("OOM - alloc_netdev\n");
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
@ -764,6 +770,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||||
|
|
||||||
ifp = netdev_priv(ndev);
|
ifp = netdev_priv(ndev);
|
||||||
ifp->ndev = ndev;
|
ifp->ndev = ndev;
|
||||||
|
}
|
||||||
|
|
||||||
ifp->drvr = drvr;
|
ifp->drvr = drvr;
|
||||||
drvr->iflist[bssidx] = ifp;
|
drvr->iflist[bssidx] = ifp;
|
||||||
ifp->ifidx = ifidx;
|
ifp->ifidx = ifidx;
|
||||||
|
@ -775,7 +783,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||||
memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
|
memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
|
||||||
|
|
||||||
brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
|
brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
|
||||||
current->pid, ifp->ndev->name, ifp->mac_addr);
|
current->pid, name, ifp->mac_addr);
|
||||||
|
|
||||||
return ifp;
|
return ifp;
|
||||||
}
|
}
|
||||||
|
@ -807,11 +815,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
||||||
}
|
}
|
||||||
|
|
||||||
unregister_netdev(ifp->ndev);
|
unregister_netdev(ifp->ndev);
|
||||||
drvr->iflist[bssidx] = NULL;
|
|
||||||
if (bssidx == 0)
|
if (bssidx == 0)
|
||||||
brcmf_cfg80211_detach(drvr->config);
|
brcmf_cfg80211_detach(drvr->config);
|
||||||
free_netdev(ifp->ndev);
|
free_netdev(ifp->ndev);
|
||||||
|
} else {
|
||||||
|
kfree(ifp);
|
||||||
}
|
}
|
||||||
|
drvr->iflist[bssidx] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
||||||
|
|
|
@ -1786,7 +1786,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "enter: idx=%d, mac=%pM\n",
|
brcmf_dbg(TRACE, "enter: idx=%d, mac=%pM\n",
|
||||||
ifp->bssidx, ifp->mac_addr);
|
ifp->bssidx, ifp->mac_addr);
|
||||||
if (!ifp->drvr->fw_signals)
|
if (!ifp->ndev || !ifp->drvr->fw_signals)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
entry = &fws->desc.iface[ifp->ifidx];
|
entry = &fws->desc.iface[ifp->ifidx];
|
||||||
|
|
|
@ -485,7 +485,6 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
|
||||||
static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
|
static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
|
||||||
{
|
{
|
||||||
struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
||||||
struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp;
|
|
||||||
bool local_admin = false;
|
bool local_admin = false;
|
||||||
|
|
||||||
if (!dev_addr || is_zero_ether_addr(dev_addr)) {
|
if (!dev_addr || is_zero_ether_addr(dev_addr)) {
|
||||||
|
@ -499,7 +498,6 @@ static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
|
||||||
memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
|
memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
|
||||||
if (local_admin)
|
if (local_admin)
|
||||||
p2p->dev_addr[0] |= 0x02;
|
p2p->dev_addr[0] |= 0x02;
|
||||||
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
|
|
||||||
|
|
||||||
/* Generate the P2P Interface Address. If the discovery and connection
|
/* Generate the P2P Interface Address. If the discovery and connection
|
||||||
* BSSCFGs need to simultaneously co-exist, then this address must be
|
* BSSCFGs need to simultaneously co-exist, then this address must be
|
||||||
|
@ -1948,6 +1946,7 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
|
||||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
|
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
|
||||||
|
|
||||||
brcmf_p2p_generate_bss_mac(p2p, NULL);
|
brcmf_p2p_generate_bss_mac(p2p, NULL);
|
||||||
|
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
|
||||||
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
|
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
|
||||||
|
|
||||||
/* Initialize P2P Discovery in the firmware */
|
/* Initialize P2P Discovery in the firmware */
|
||||||
|
@ -2163,38 +2162,44 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
|
||||||
return (struct wireless_dev *)p2p_vif;
|
return (struct wireless_dev *)p2p_vif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create ifp here */
|
|
||||||
p2p_ifp = kzalloc(sizeof(*p2p_ifp), GFP_KERNEL);
|
|
||||||
if (!p2p_ifp)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
|
|
||||||
p2p_vif->ifp = p2p_ifp;
|
|
||||||
p2p_ifp->vif = p2p_vif;
|
|
||||||
|
|
||||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
|
|
||||||
brcmf_p2p_generate_bss_mac(p2p, addr);
|
|
||||||
memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr));
|
|
||||||
|
|
||||||
pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
||||||
|
brcmf_p2p_generate_bss_mac(p2p, addr);
|
||||||
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
|
brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
|
||||||
|
|
||||||
|
brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif);
|
||||||
|
|
||||||
/* Initialize P2P Discovery in the firmware */
|
/* Initialize P2P Discovery in the firmware */
|
||||||
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
|
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
brcmf_err("set p2p_disc error\n");
|
brcmf_err("set p2p_disc error\n");
|
||||||
brcmf_free_vif(p2p_vif);
|
brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
|
||||||
return ERR_PTR(err);
|
goto fail;
|
||||||
}
|
}
|
||||||
/* obtain bsscfg index for P2P discovery */
|
|
||||||
|
/* wait for firmware event */
|
||||||
|
err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD,
|
||||||
|
msecs_to_jiffies(1500));
|
||||||
|
brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
|
||||||
|
if (!err) {
|
||||||
|
brcmf_err("timeout occurred\n");
|
||||||
|
err = -EIO;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* discovery interface created */
|
||||||
|
p2p_ifp = p2p_vif->ifp;
|
||||||
|
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
|
||||||
|
memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
|
||||||
|
memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr));
|
||||||
|
|
||||||
|
/* verify bsscfg index for P2P discovery */
|
||||||
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
|
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
brcmf_err("retrieving discover bsscfg index failed\n");
|
brcmf_err("retrieving discover bsscfg index failed\n");
|
||||||
brcmf_free_vif(p2p_vif);
|
goto fail;
|
||||||
return ERR_PTR(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p2p_ifp->drvr = p2p->cfg->pub;
|
WARN_ON(p2p_ifp->bssidx != bssidx);
|
||||||
p2p_ifp->bssidx = bssidx;
|
|
||||||
|
|
||||||
init_completion(&p2p->send_af_done);
|
init_completion(&p2p->send_af_done);
|
||||||
INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
|
INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
|
||||||
|
@ -2202,6 +2207,10 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
|
||||||
init_completion(&p2p->wait_next_af);
|
init_completion(&p2p->wait_next_af);
|
||||||
|
|
||||||
return &p2p_vif->wdev;
|
return &p2p_vif->wdev;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
brcmf_free_vif(p2p_vif);
|
||||||
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2215,7 +2224,6 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_vif *vif)
|
||||||
|
|
||||||
cfg80211_unregister_wdev(&vif->wdev);
|
cfg80211_unregister_wdev(&vif->wdev);
|
||||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||||
kfree(vif->ifp);
|
|
||||||
brcmf_free_vif(vif);
|
brcmf_free_vif(vif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4568,9 +4568,11 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
|
||||||
|
|
||||||
ifp->vif = vif;
|
ifp->vif = vif;
|
||||||
vif->ifp = ifp;
|
vif->ifp = ifp;
|
||||||
|
if (ifp->ndev) {
|
||||||
vif->wdev.netdev = ifp->ndev;
|
vif->wdev.netdev = ifp->ndev;
|
||||||
ifp->ndev->ieee80211_ptr = &vif->wdev;
|
ifp->ndev->ieee80211_ptr = &vif->wdev;
|
||||||
SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
|
SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
|
||||||
|
}
|
||||||
mutex_unlock(&event->vif_event_lock);
|
mutex_unlock(&event->vif_event_lock);
|
||||||
wake_up(&event->vif_wq);
|
wake_up(&event->vif_wq);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue