aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c147
1 files changed, 92 insertions, 55 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 069a4e46812..21d6ab358c8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -49,6 +49,8 @@
49#define BRCMF_PNO_SCAN_COMPLETE 1 49#define BRCMF_PNO_SCAN_COMPLETE 1
50#define BRCMF_PNO_SCAN_INCOMPLETE 0 50#define BRCMF_PNO_SCAN_INCOMPLETE 0
51 51
52#define BRCMF_IFACE_MAX_CNT 2
53
52#define TLV_LEN_OFF 1 /* length offset */ 54#define TLV_LEN_OFF 1 /* length offset */
53#define TLV_HDR_LEN 2 /* header length */ 55#define TLV_HDR_LEN 2 /* header length */
54#define TLV_BODY_OFF 2 /* body offset */ 56#define TLV_BODY_OFF 2 /* body offset */
@@ -3441,7 +3443,7 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
3441static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) 3443static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
3442{ 3444{
3443 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); 3445 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3444 struct net_device *ndev = cfg->wdev->netdev; 3446 struct net_device *ndev = cfg_to_ndev(cfg);
3445 struct brcmf_dcmd *dcmd = data; 3447 struct brcmf_dcmd *dcmd = data;
3446 struct sk_buff *reply; 3448 struct sk_buff *reply;
3447 int ret; 3449 int ret;
@@ -4194,72 +4196,95 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
4194#endif 4196#endif
4195} 4197}
4196 4198
4197static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) 4199static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
4198{ 4200{
4199 struct wireless_dev *wdev; 4201 struct wiphy *wiphy;
4200 s32 err = 0; 4202 s32 err = 0;
4201 4203
4202 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); 4204 wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
4203 if (!wdev) 4205 if (!wiphy) {
4204 return ERR_PTR(-ENOMEM);
4205
4206 wdev->wiphy = wiphy_new(&wl_cfg80211_ops,
4207 sizeof(struct brcmf_cfg80211_info));
4208 if (!wdev->wiphy) {
4209 WL_ERR("Could not allocate wiphy device\n"); 4206 WL_ERR("Could not allocate wiphy device\n");
4210 err = -ENOMEM; 4207 return ERR_PTR(-ENOMEM);
4211 goto wiphy_new_out; 4208 }
4212 } 4209 set_wiphy_dev(wiphy, phydev);
4213 set_wiphy_dev(wdev->wiphy, ndev); 4210 wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
4214 wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; 4211 wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
4215 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; 4212 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
4216 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 4213 BIT(NL80211_IFTYPE_ADHOC) |
4217 BIT(NL80211_IFTYPE_ADHOC) | 4214 BIT(NL80211_IFTYPE_AP);
4218 BIT(NL80211_IFTYPE_AP); 4215 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
4219 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; 4216 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
4220 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
4221 * it as 11a by default. 4217 * it as 11a by default.
4222 * This will be updated with 4218 * This will be updated with
4223 * 11n phy tables in 4219 * 11n phy tables in
4224 * "ifconfig up" 4220 * "ifconfig up"
4225 * if phy has 11n capability 4221 * if phy has 11n capability
4226 */ 4222 */
4227 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 4223 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4228 wdev->wiphy->cipher_suites = __wl_cipher_suites; 4224 wiphy->cipher_suites = __wl_cipher_suites;
4229 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); 4225 wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
4230 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power 4226 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
4231 * save mode 4227 * save mode
4232 * by default 4228 * by default
4233 */ 4229 */
4234 brcmf_wiphy_pno_params(wdev->wiphy); 4230 brcmf_wiphy_pno_params(wiphy);
4235 err = wiphy_register(wdev->wiphy); 4231 err = wiphy_register(wiphy);
4236 if (err < 0) { 4232 if (err < 0) {
4237 WL_ERR("Could not register wiphy device (%d)\n", err); 4233 WL_ERR("Could not register wiphy device (%d)\n", err);
4238 goto wiphy_register_out; 4234 wiphy_free(wiphy);
4235 return ERR_PTR(err);
4239 } 4236 }
4240 return wdev; 4237 return wiphy;
4238}
4239
4240static
4241struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
4242 struct net_device *netdev,
4243 s32 mode, bool pm_block)
4244{
4245 struct brcmf_cfg80211_vif *vif;
4246
4247 if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
4248 return ERR_PTR(-ENOSPC);
4249
4250 vif = kzalloc(sizeof(*vif), GFP_KERNEL);
4251 if (!vif)
4252 return ERR_PTR(-ENOMEM);
4241 4253
4242wiphy_register_out: 4254 vif->wdev.wiphy = cfg->wiphy;
4243 wiphy_free(wdev->wiphy); 4255 vif->wdev.netdev = netdev;
4256 vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode);
4244 4257
4245wiphy_new_out: 4258 if (netdev) {
4246 kfree(wdev); 4259 vif->ifp = netdev_priv(netdev);
4260 netdev->ieee80211_ptr = &vif->wdev;
4261 SET_NETDEV_DEV(netdev, wiphy_dev(cfg->wiphy));
4262 }
4263
4264 vif->mode = mode;
4265 vif->pm_block = pm_block;
4266 vif->roam_off = -1;
4247 4267
4248 return ERR_PTR(err); 4268 list_add_tail(&vif->list, &cfg->vif_list);
4269 cfg->vif_cnt++;
4270 return vif;
4249} 4271}
4250 4272
4251static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg) 4273static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
4252{ 4274{
4253 struct wireless_dev *wdev = cfg->wdev; 4275 struct brcmf_cfg80211_info *cfg;
4276 struct wiphy *wiphy;
4254 4277
4255 if (!wdev) { 4278 wiphy = vif->wdev.wiphy;
4256 WL_ERR("wdev is invalid\n"); 4279 cfg = wiphy_priv(wiphy);
4257 return; 4280 list_del(&vif->list);
4281 cfg->vif_cnt--;
4282
4283 kfree(vif);
4284 if (!cfg->vif_cnt) {
4285 wiphy_unregister(wiphy);
4286 wiphy_free(wiphy);
4258 } 4287 }
4259 wiphy_unregister(wdev->wiphy);
4260 wiphy_free(wdev->wiphy);
4261 kfree(wdev);
4262 cfg->wdev = NULL;
4263} 4288}
4264 4289
4265static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, 4290static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg,
@@ -4935,8 +4960,10 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr)
4935{ 4960{
4936 struct net_device *ndev = drvr->iflist[0]->ndev; 4961 struct net_device *ndev = drvr->iflist[0]->ndev;
4937 struct device *busdev = drvr->dev; 4962 struct device *busdev = drvr->dev;
4938 struct wireless_dev *wdev;
4939 struct brcmf_cfg80211_info *cfg; 4963 struct brcmf_cfg80211_info *cfg;
4964 struct wiphy *wiphy;
4965 struct brcmf_cfg80211_vif *vif;
4966 struct brcmf_if *ifp;
4940 s32 err = 0; 4967 s32 err = 0;
4941 4968
4942 if (!ndev) { 4969 if (!ndev) {
@@ -4944,35 +4971,45 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr)
4944 return NULL; 4971 return NULL;
4945 } 4972 }
4946 4973
4947 wdev = brcmf_alloc_wdev(busdev); 4974 ifp = netdev_priv(ndev);
4948 if (IS_ERR(wdev)) { 4975 wiphy = brcmf_setup_wiphy(busdev);
4976 if (IS_ERR(wiphy))
4949 return NULL; 4977 return NULL;
4950 }
4951 4978
4952 wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); 4979 cfg = wiphy_priv(wiphy);
4953 cfg = wdev_to_cfg(wdev); 4980 cfg->wiphy = wiphy;
4954 cfg->wdev = wdev;
4955 cfg->pub = drvr; 4981 cfg->pub = drvr;
4956 ndev->ieee80211_ptr = wdev; 4982 INIT_LIST_HEAD(&cfg->vif_list);
4957 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); 4983
4958 wdev->netdev = ndev; 4984 vif = brcmf_alloc_vif(cfg, ndev, WL_MODE_BSS, false);
4985 if (IS_ERR(vif)) {
4986 wiphy_free(wiphy);
4987 return NULL;
4988 }
4989
4959 err = wl_init_priv(cfg); 4990 err = wl_init_priv(cfg);
4960 if (err) { 4991 if (err) {
4961 WL_ERR("Failed to init iwm_priv (%d)\n", err); 4992 WL_ERR("Failed to init iwm_priv (%d)\n", err);
4962 goto cfg80211_attach_out; 4993 goto cfg80211_attach_out;
4963 } 4994 }
4964 4995
4996 ifp->vif = vif;
4965 return cfg; 4997 return cfg;
4966 4998
4967cfg80211_attach_out: 4999cfg80211_attach_out:
4968 brcmf_free_wdev(cfg); 5000 brcmf_free_vif(vif);
4969 return NULL; 5001 return NULL;
4970} 5002}
4971 5003
4972void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) 5004void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
4973{ 5005{
5006 struct brcmf_cfg80211_vif *vif;
5007 struct brcmf_cfg80211_vif *tmp;
5008
4974 wl_deinit_priv(cfg); 5009 wl_deinit_priv(cfg);
4975 brcmf_free_wdev(cfg); 5010 list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
5011 brcmf_free_vif(vif);
5012 }
4976} 5013}
4977 5014
4978void 5015void