summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2013-04-05 10:57:51 +0200
committerJohn W. Linville <linville@tuxdriver.com>2013-04-08 21:28:46 +0200
commit01b8e7db61fbe575193ea2c6eda1964c1d9b8b07 (patch)
tree2565e5daa37b2a77e68657676e73ab97b5367e89 /drivers/net/wireless/brcm80211/brcmfmac/p2p.c
parentbrcmfmac: support creation of P2P_DEVICE through user-space (diff)
downloadlinux-01b8e7db61fbe575193ea2c6eda1964c1d9b8b07.tar.xz
linux-01b8e7db61fbe575193ea2c6eda1964c1d9b8b07.zip
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>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/p2p.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.c52
1 files changed, 30 insertions, 22 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index 5d5d1e48a383..c3d98362947f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -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)
{
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;
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);
if (local_admin)
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
* 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;
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);
/* 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;
}
- /* 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;
+ brcmf_p2p_generate_bss_mac(p2p, 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 */
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
if (err < 0) {
brcmf_err("set p2p_disc error\n");
- brcmf_free_vif(p2p_vif);
- return ERR_PTR(err);
+ brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
+ 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);
if (err < 0) {
brcmf_err("retrieving discover bsscfg index failed\n");
- brcmf_free_vif(p2p_vif);
- return ERR_PTR(err);
+ goto fail;
}
- p2p_ifp->drvr = p2p->cfg->pub;
- p2p_ifp->bssidx = bssidx;
+ WARN_ON(p2p_ifp->bssidx != bssidx);
init_completion(&p2p->send_af_done);
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);
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);
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
- kfree(vif->ifp);
brcmf_free_vif(vif);
}