Search Linux Wireless

[PATCH 2/4] brcmfmac: support virtual interface creation from firmware

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Double Lo <double.lo@xxxxxxxxxxx>

Allow interface creation via IF_ADD event from firmware.

Signed-off-by: Double Lo <double.lo@xxxxxxxxxxx>
Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@xxxxxxxxxxx>
---
 .../broadcom/brcm80211/brcmfmac/cfg80211.c    | 46 +++++++++++++++++--
 1 file changed, 43 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index a757abd7a599..900376dc0b67 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -230,6 +230,9 @@ struct parsed_vndr_ies {
        struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
 };

+#define WLC_E_IF_ROLE_STA              0       /* Infra STA */
+#define WLC_E_IF_ROLE_AP               1       /* Access Point */
+
 static u8 nl80211_band_to_fwil(enum nl80211_band band)
 {
        switch (band) {
@@ -5532,8 +5535,10 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev)
        ifp = netdev_priv(ndev);
        vif = ifp->vif;

-       if (vif)
+       if (vif) {
                brcmf_free_vif(vif);
+               ifp->vif = NULL;
+       }
 }

 static bool brcmf_is_linkup(struct brcmf_cfg80211_vif *vif,
@@ -6090,6 +6095,9 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
        struct brcmf_if_event *ifevent = (struct brcmf_if_event *)data;
        struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
        struct brcmf_cfg80211_vif *vif;
+       enum nl80211_iftype iftype = NL80211_IFTYPE_UNSPECIFIED;
+       bool vif_pend = false;
+       int err;

        brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfgidx %u\n",
                  ifevent->action, ifevent->flags, ifevent->ifidx,
@@ -6102,9 +6110,28 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
        switch (ifevent->action) {
        case BRCMF_E_IF_ADD:
                /* waiting process may have timed out */
-               if (!cfg->vif_event.vif) {
+               if (!vif) {
+                       /* handle IF_ADD event from firmware */
                        spin_unlock(&event->vif_event_lock);
-                       return -EBADF;
+                       vif_pend = true;
+                       if (ifevent->role == WLC_E_IF_ROLE_STA)
+                               iftype = NL80211_IFTYPE_STATION;
+                       else if (ifevent->role == WLC_E_IF_ROLE_AP)
+                               iftype = NL80211_IFTYPE_AP;
+                       else
+                               vif_pend = false;
+
+                       if (vif_pend) {
+                               vif = brcmf_alloc_vif(cfg, iftype);
+                               if (IS_ERR(vif)) {
+                                       brcmf_err("Role:%d failed to alloc vif\n",
+                                                 ifevent->role);
+                                       return PTR_ERR(vif);
+                               }
+                       } else {
+                               brcmf_err("Invalid Role:%d\n", ifevent->role);
+                               return -EBADF;
+                       }
                }

                ifp->vif = vif;
@@ -6114,6 +6141,19 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
                        ifp->ndev->ieee80211_ptr = &vif->wdev;
                        SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
                }
+
+               if (vif_pend) {
+                       err = brcmf_net_attach(ifp, false);
+                       if (err) {
+                               brcmf_err("netdevice register failed with err:%d\n",
+                                         err);
+                               brcmf_free_vif(vif);
+                               free_netdev(ifp->ndev);
+                       }
+                       spin_unlock(&event->vif_event_lock);
+                       return err;
+               }
+
                spin_unlock(&event->vif_event_lock);
                wake_up(&event->vif_wq);
                return 0;
--
2.25.0


This message and any attachments may contain confidential information from Cypress or its subsidiaries. If it has been received in error, please advise the sender and immediately delete this message.




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux