diff options
author | Arend van Spriel <arend@broadcom.com> | 2013-04-05 04:57:51 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-08 15:28:46 -0400 |
commit | 01b8e7db61fbe575193ea2c6eda1964c1d9b8b07 (patch) | |
tree | 2565e5daa37b2a77e68657676e73ab97b5367e89 /drivers/net/wireless | |
parent | 27f10e380ad912c7928e08c4d04b246e66022cc4 (diff) |
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')
4 files changed, 55 insertions, 35 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index c82f3e0b66f9..e68500bb63e7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -755,15 +755,23 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, | |||
755 | } | 755 | } |
756 | } | 756 | } |
757 | 757 | ||
758 | /* Allocate netdev, including space for private structure */ | 758 | if (!brcmf_p2p_enable && bssidx == 1) { |
759 | ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup); | 759 | /* this is P2P_DEVICE interface */ |
760 | if (!ndev) { | 760 | brcmf_dbg(INFO, "allocate non-netdev interface\n"); |
761 | brcmf_err("OOM - alloc_netdev\n"); | 761 | ifp = kzalloc(sizeof(*ifp), GFP_KERNEL); |
762 | return ERR_PTR(-ENOMEM); | 762 | } else { |
763 | brcmf_dbg(INFO, "allocate netdev interface\n"); | ||
764 | /* Allocate netdev, including space for private structure */ | ||
765 | ndev = alloc_netdev(sizeof(*ifp), name, ether_setup); | ||
766 | if (!ndev) { | ||
767 | brcmf_err("OOM - alloc_netdev\n"); | ||
768 | return ERR_PTR(-ENOMEM); | ||
769 | } | ||
770 | |||
771 | ifp = netdev_priv(ndev); | ||
772 | ifp->ndev = ndev; | ||
763 | } | 773 | } |
764 | 774 | ||
765 | ifp = netdev_priv(ndev); | ||
766 | ifp->ndev = ndev; | ||
767 | ifp->drvr = drvr; | 775 | ifp->drvr = drvr; |
768 | drvr->iflist[bssidx] = ifp; | 776 | drvr->iflist[bssidx] = ifp; |
769 | ifp->ifidx = ifidx; | 777 | ifp->ifidx = ifidx; |
@@ -775,7 +783,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, | |||
775 | memcpy(ifp->mac_addr, mac_addr, ETH_ALEN); | 783 | memcpy(ifp->mac_addr, mac_addr, ETH_ALEN); |
776 | 784 | ||
777 | brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n", | 785 | brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n", |
778 | current->pid, ifp->ndev->name, ifp->mac_addr); | 786 | current->pid, name, ifp->mac_addr); |
779 | 787 | ||
780 | return ifp; | 788 | return ifp; |
781 | } | 789 | } |
@@ -807,11 +815,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) | |||
807 | } | 815 | } |
808 | 816 | ||
809 | unregister_netdev(ifp->ndev); | 817 | unregister_netdev(ifp->ndev); |
810 | drvr->iflist[bssidx] = NULL; | ||
811 | if (bssidx == 0) | 818 | if (bssidx == 0) |
812 | brcmf_cfg80211_detach(drvr->config); | 819 | brcmf_cfg80211_detach(drvr->config); |
813 | free_netdev(ifp->ndev); | 820 | free_netdev(ifp->ndev); |
821 | } else { | ||
822 | kfree(ifp); | ||
814 | } | 823 | } |
824 | drvr->iflist[bssidx] = NULL; | ||
815 | } | 825 | } |
816 | 826 | ||
817 | int brcmf_attach(uint bus_hdrlen, struct device *dev) | 827 | int brcmf_attach(uint bus_hdrlen, struct device *dev) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 619fff34c218..b3c608ee37cf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -1786,7 +1786,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp) | |||
1786 | 1786 | ||
1787 | brcmf_dbg(TRACE, "enter: idx=%d, mac=%pM\n", | 1787 | brcmf_dbg(TRACE, "enter: idx=%d, mac=%pM\n", |
1788 | ifp->bssidx, ifp->mac_addr); | 1788 | ifp->bssidx, ifp->mac_addr); |
1789 | if (!ifp->drvr->fw_signals) | 1789 | if (!ifp->ndev || !ifp->drvr->fw_signals) |
1790 | return; | 1790 | return; |
1791 | 1791 | ||
1792 | entry = &fws->desc.iface[ifp->ifidx]; | 1792 | entry = &fws->desc.iface[ifp->ifidx]; |
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) | |||
485 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) | 485 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) |
486 | { | 486 | { |
487 | struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 487 | struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; |
488 | struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp; | ||
489 | bool local_admin = false; | 488 | bool local_admin = false; |
490 | 489 | ||
491 | if (!dev_addr || is_zero_ether_addr(dev_addr)) { | 490 | 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) | |||
499 | memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); | 498 | memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); |
500 | if (local_admin) | 499 | if (local_admin) |
501 | p2p->dev_addr[0] |= 0x02; | 500 | p2p->dev_addr[0] |= 0x02; |
502 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
503 | 501 | ||
504 | /* Generate the P2P Interface Address. If the discovery and connection | 502 | /* Generate the P2P Interface Address. If the discovery and connection |
505 | * BSSCFGs need to simultaneously co-exist, then this address must be | 503 | * BSSCFGs need to simultaneously co-exist, then this address must be |
@@ -1948,6 +1946,7 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) | |||
1948 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | 1946 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; |
1949 | 1947 | ||
1950 | brcmf_p2p_generate_bss_mac(p2p, NULL); | 1948 | brcmf_p2p_generate_bss_mac(p2p, NULL); |
1949 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
1951 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | 1950 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); |
1952 | 1951 | ||
1953 | /* Initialize P2P Discovery in the firmware */ | 1952 | /* Initialize P2P Discovery in the firmware */ |
@@ -2163,38 +2162,44 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, | |||
2163 | return (struct wireless_dev *)p2p_vif; | 2162 | return (struct wireless_dev *)p2p_vif; |
2164 | } | 2163 | } |
2165 | 2164 | ||
2166 | /* create ifp here */ | ||
2167 | p2p_ifp = kzalloc(sizeof(*p2p_ifp), GFP_KERNEL); | ||
2168 | if (!p2p_ifp) | ||
2169 | return ERR_PTR(-ENOMEM); | ||
2170 | |||
2171 | p2p_vif->ifp = p2p_ifp; | ||
2172 | p2p_ifp->vif = p2p_vif; | ||
2173 | |||
2174 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | ||
2175 | brcmf_p2p_generate_bss_mac(p2p, addr); | ||
2176 | memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr)); | ||
2177 | |||
2178 | pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 2165 | pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; |
2166 | brcmf_p2p_generate_bss_mac(p2p, addr); | ||
2179 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | 2167 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); |
2180 | 2168 | ||
2169 | brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif); | ||
2170 | |||
2181 | /* Initialize P2P Discovery in the firmware */ | 2171 | /* Initialize P2P Discovery in the firmware */ |
2182 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); | 2172 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); |
2183 | if (err < 0) { | 2173 | if (err < 0) { |
2184 | brcmf_err("set p2p_disc error\n"); | 2174 | brcmf_err("set p2p_disc error\n"); |
2185 | brcmf_free_vif(p2p_vif); | 2175 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); |
2186 | return ERR_PTR(err); | 2176 | goto fail; |
2187 | } | 2177 | } |
2188 | /* obtain bsscfg index for P2P discovery */ | 2178 | |
2179 | /* wait for firmware event */ | ||
2180 | err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD, | ||
2181 | msecs_to_jiffies(1500)); | ||
2182 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); | ||
2183 | if (!err) { | ||
2184 | brcmf_err("timeout occurred\n"); | ||
2185 | err = -EIO; | ||
2186 | goto fail; | ||
2187 | } | ||
2188 | |||
2189 | /* discovery interface created */ | ||
2190 | p2p_ifp = p2p_vif->ifp; | ||
2191 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | ||
2192 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
2193 | memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr)); | ||
2194 | |||
2195 | /* verify bsscfg index for P2P discovery */ | ||
2189 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); | 2196 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); |
2190 | if (err < 0) { | 2197 | if (err < 0) { |
2191 | brcmf_err("retrieving discover bsscfg index failed\n"); | 2198 | brcmf_err("retrieving discover bsscfg index failed\n"); |
2192 | brcmf_free_vif(p2p_vif); | 2199 | goto fail; |
2193 | return ERR_PTR(err); | ||
2194 | } | 2200 | } |
2195 | 2201 | ||
2196 | p2p_ifp->drvr = p2p->cfg->pub; | 2202 | WARN_ON(p2p_ifp->bssidx != bssidx); |
2197 | p2p_ifp->bssidx = bssidx; | ||
2198 | 2203 | ||
2199 | init_completion(&p2p->send_af_done); | 2204 | init_completion(&p2p->send_af_done); |
2200 | INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); | 2205 | 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, | |||
2202 | init_completion(&p2p->wait_next_af); | 2207 | init_completion(&p2p->wait_next_af); |
2203 | 2208 | ||
2204 | return &p2p_vif->wdev; | 2209 | return &p2p_vif->wdev; |
2210 | |||
2211 | fail: | ||
2212 | brcmf_free_vif(p2p_vif); | ||
2213 | return ERR_PTR(err); | ||
2205 | } | 2214 | } |
2206 | 2215 | ||
2207 | /** | 2216 | /** |
@@ -2215,7 +2224,6 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_vif *vif) | |||
2215 | 2224 | ||
2216 | cfg80211_unregister_wdev(&vif->wdev); | 2225 | cfg80211_unregister_wdev(&vif->wdev); |
2217 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; | 2226 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; |
2218 | kfree(vif->ifp); | ||
2219 | brcmf_free_vif(vif); | 2227 | brcmf_free_vif(vif); |
2220 | } | 2228 | } |
2221 | 2229 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index cba757b792b0..68859e534420 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -4568,9 +4568,11 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp, | |||
4568 | 4568 | ||
4569 | ifp->vif = vif; | 4569 | ifp->vif = vif; |
4570 | vif->ifp = ifp; | 4570 | vif->ifp = ifp; |
4571 | vif->wdev.netdev = ifp->ndev; | 4571 | if (ifp->ndev) { |
4572 | ifp->ndev->ieee80211_ptr = &vif->wdev; | 4572 | vif->wdev.netdev = ifp->ndev; |
4573 | SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy)); | 4573 | ifp->ndev->ieee80211_ptr = &vif->wdev; |
4574 | SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy)); | ||
4575 | } | ||
4574 | mutex_unlock(&event->vif_event_lock); | 4576 | mutex_unlock(&event->vif_event_lock); |
4575 | wake_up(&event->vif_wq); | 4577 | wake_up(&event->vif_wq); |
4576 | return 0; | 4578 | return 0; |