diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 147 |
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, | |||
3441 | static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) | 3443 | static 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 | ||
4197 | static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) | 4199 | static 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 | |||
4240 | static | ||
4241 | struct 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 | ||
4242 | wiphy_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 | ||
4245 | wiphy_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 | ||
4251 | static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg) | 4273 | static 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 | ||
4265 | static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, | 4290 | 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) | |||
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 | ||
4967 | cfg80211_attach_out: | 4999 | cfg80211_attach_out: |
4968 | brcmf_free_wdev(cfg); | 5000 | brcmf_free_vif(vif); |
4969 | return NULL; | 5001 | return NULL; |
4970 | } | 5002 | } |
4971 | 5003 | ||
4972 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | 5004 | void 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 | ||
4978 | void | 5015 | void |