|
@@ -49,6 +49,8 @@
|
|
|
#define BRCMF_PNO_SCAN_COMPLETE 1
|
|
|
#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
|
|
|
|
|
+#define BRCMF_IFACE_MAX_CNT 2
|
|
|
+
|
|
|
#define TLV_LEN_OFF 1 /* length offset */
|
|
|
#define TLV_HDR_LEN 2 /* header length */
|
|
|
#define TLV_BODY_OFF 2 /* body offset */
|
|
@@ -3441,7 +3443,7 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
|
|
|
static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
|
|
|
{
|
|
|
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
|
|
- struct net_device *ndev = cfg->wdev->netdev;
|
|
|
+ struct net_device *ndev = cfg_to_ndev(cfg);
|
|
|
struct brcmf_dcmd *dcmd = data;
|
|
|
struct sk_buff *reply;
|
|
|
int ret;
|
|
@@ -4194,72 +4196,95 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev)
|
|
|
+static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
|
|
|
{
|
|
|
- struct wireless_dev *wdev;
|
|
|
+ struct wiphy *wiphy;
|
|
|
s32 err = 0;
|
|
|
|
|
|
- wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
|
|
|
- if (!wdev)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
-
|
|
|
- wdev->wiphy = wiphy_new(&wl_cfg80211_ops,
|
|
|
- sizeof(struct brcmf_cfg80211_info));
|
|
|
- if (!wdev->wiphy) {
|
|
|
+ wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
|
|
|
+ if (!wiphy) {
|
|
|
WL_ERR("Could not allocate wiphy device\n");
|
|
|
- err = -ENOMEM;
|
|
|
- goto wiphy_new_out;
|
|
|
- }
|
|
|
- set_wiphy_dev(wdev->wiphy, ndev);
|
|
|
- wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
|
|
|
- wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
|
|
|
- wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
|
|
- BIT(NL80211_IFTYPE_ADHOC) |
|
|
|
- BIT(NL80211_IFTYPE_AP);
|
|
|
- wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
|
|
|
- wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+ }
|
|
|
+ set_wiphy_dev(wiphy, phydev);
|
|
|
+ wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
|
|
|
+ wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
|
|
|
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
|
|
+ BIT(NL80211_IFTYPE_ADHOC) |
|
|
|
+ BIT(NL80211_IFTYPE_AP);
|
|
|
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
|
|
|
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
|
|
|
* it as 11a by default.
|
|
|
* This will be updated with
|
|
|
* 11n phy tables in
|
|
|
* "ifconfig up"
|
|
|
* if phy has 11n capability
|
|
|
*/
|
|
|
- wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
|
|
- wdev->wiphy->cipher_suites = __wl_cipher_suites;
|
|
|
- wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
|
|
|
- wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
|
|
|
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
|
|
+ wiphy->cipher_suites = __wl_cipher_suites;
|
|
|
+ wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
|
|
|
+ wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
|
|
|
* save mode
|
|
|
* by default
|
|
|
*/
|
|
|
- brcmf_wiphy_pno_params(wdev->wiphy);
|
|
|
- err = wiphy_register(wdev->wiphy);
|
|
|
+ brcmf_wiphy_pno_params(wiphy);
|
|
|
+ err = wiphy_register(wiphy);
|
|
|
if (err < 0) {
|
|
|
WL_ERR("Could not register wiphy device (%d)\n", err);
|
|
|
- goto wiphy_register_out;
|
|
|
+ wiphy_free(wiphy);
|
|
|
+ return ERR_PTR(err);
|
|
|
}
|
|
|
- return wdev;
|
|
|
+ return wiphy;
|
|
|
+}
|
|
|
+
|
|
|
+static
|
|
|
+struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
|
|
+ struct net_device *netdev,
|
|
|
+ s32 mode, bool pm_block)
|
|
|
+{
|
|
|
+ struct brcmf_cfg80211_vif *vif;
|
|
|
+
|
|
|
+ if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
|
|
|
+ return ERR_PTR(-ENOSPC);
|
|
|
+
|
|
|
+ vif = kzalloc(sizeof(*vif), GFP_KERNEL);
|
|
|
+ if (!vif)
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
-wiphy_register_out:
|
|
|
- wiphy_free(wdev->wiphy);
|
|
|
+ vif->wdev.wiphy = cfg->wiphy;
|
|
|
+ vif->wdev.netdev = netdev;
|
|
|
+ vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode);
|
|
|
|
|
|
-wiphy_new_out:
|
|
|
- kfree(wdev);
|
|
|
+ if (netdev) {
|
|
|
+ vif->ifp = netdev_priv(netdev);
|
|
|
+ netdev->ieee80211_ptr = &vif->wdev;
|
|
|
+ SET_NETDEV_DEV(netdev, wiphy_dev(cfg->wiphy));
|
|
|
+ }
|
|
|
+
|
|
|
+ vif->mode = mode;
|
|
|
+ vif->pm_block = pm_block;
|
|
|
+ vif->roam_off = -1;
|
|
|
|
|
|
- return ERR_PTR(err);
|
|
|
+ list_add_tail(&vif->list, &cfg->vif_list);
|
|
|
+ cfg->vif_cnt++;
|
|
|
+ return vif;
|
|
|
}
|
|
|
|
|
|
-static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg)
|
|
|
+static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
|
|
|
{
|
|
|
- struct wireless_dev *wdev = cfg->wdev;
|
|
|
+ struct brcmf_cfg80211_info *cfg;
|
|
|
+ struct wiphy *wiphy;
|
|
|
|
|
|
- if (!wdev) {
|
|
|
- WL_ERR("wdev is invalid\n");
|
|
|
- return;
|
|
|
+ wiphy = vif->wdev.wiphy;
|
|
|
+ cfg = wiphy_priv(wiphy);
|
|
|
+ list_del(&vif->list);
|
|
|
+ cfg->vif_cnt--;
|
|
|
+
|
|
|
+ kfree(vif);
|
|
|
+ if (!cfg->vif_cnt) {
|
|
|
+ wiphy_unregister(wiphy);
|
|
|
+ wiphy_free(wiphy);
|
|
|
}
|
|
|
- wiphy_unregister(wdev->wiphy);
|
|
|
- wiphy_free(wdev->wiphy);
|
|
|
- kfree(wdev);
|
|
|
- cfg->wdev = NULL;
|
|
|
}
|
|
|
|
|
|
static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg,
|
|
@@ -4935,8 +4960,10 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr)
|
|
|
{
|
|
|
struct net_device *ndev = drvr->iflist[0]->ndev;
|
|
|
struct device *busdev = drvr->dev;
|
|
|
- struct wireless_dev *wdev;
|
|
|
struct brcmf_cfg80211_info *cfg;
|
|
|
+ struct wiphy *wiphy;
|
|
|
+ struct brcmf_cfg80211_vif *vif;
|
|
|
+ struct brcmf_if *ifp;
|
|
|
s32 err = 0;
|
|
|
|
|
|
if (!ndev) {
|
|
@@ -4944,35 +4971,45 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- wdev = brcmf_alloc_wdev(busdev);
|
|
|
- if (IS_ERR(wdev)) {
|
|
|
+ ifp = netdev_priv(ndev);
|
|
|
+ wiphy = brcmf_setup_wiphy(busdev);
|
|
|
+ if (IS_ERR(wiphy))
|
|
|
return NULL;
|
|
|
- }
|
|
|
|
|
|
- wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
|
|
|
- cfg = wdev_to_cfg(wdev);
|
|
|
- cfg->wdev = wdev;
|
|
|
+ cfg = wiphy_priv(wiphy);
|
|
|
+ cfg->wiphy = wiphy;
|
|
|
cfg->pub = drvr;
|
|
|
- ndev->ieee80211_ptr = wdev;
|
|
|
- SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
|
|
|
- wdev->netdev = ndev;
|
|
|
+ INIT_LIST_HEAD(&cfg->vif_list);
|
|
|
+
|
|
|
+ vif = brcmf_alloc_vif(cfg, ndev, WL_MODE_BSS, false);
|
|
|
+ if (IS_ERR(vif)) {
|
|
|
+ wiphy_free(wiphy);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
err = wl_init_priv(cfg);
|
|
|
if (err) {
|
|
|
WL_ERR("Failed to init iwm_priv (%d)\n", err);
|
|
|
goto cfg80211_attach_out;
|
|
|
}
|
|
|
|
|
|
+ ifp->vif = vif;
|
|
|
return cfg;
|
|
|
|
|
|
cfg80211_attach_out:
|
|
|
- brcmf_free_wdev(cfg);
|
|
|
+ brcmf_free_vif(vif);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
|
|
|
{
|
|
|
+ struct brcmf_cfg80211_vif *vif;
|
|
|
+ struct brcmf_cfg80211_vif *tmp;
|
|
|
+
|
|
|
wl_deinit_priv(cfg);
|
|
|
- brcmf_free_wdev(cfg);
|
|
|
+ list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
|
|
|
+ brcmf_free_vif(vif);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void
|