aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2012-10-22 16:55:30 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-10-29 15:28:43 -0400
commit3eacf866559c3d2062690bab8bf09f15f963fb16 (patch)
tree4ae1a95e5968fdce933fee891cefd20fbe9d84bf
parentec6de0ed3ecfab6acfa11c32f9acc9b3c6a5adc7 (diff)
brcmfmac: introduce brcmf_cfg80211_vif structure
This patch introduces the brcmf_cfg80211_vif structure which is used to keep track of multiple virtual interfaces in the driver. Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Franky Lin <frankyl@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c147
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h39
3 files changed, 129 insertions, 62 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index bde5e253e0ed..8704daa2758f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -682,10 +682,14 @@ struct brcmf_if_event {
682 u8 bssidx; 682 u8 bssidx;
683}; 683};
684 684
685/* forward declaration */
686struct brcmf_cfg80211_vif;
687
685/** 688/**
686 * struct brcmf_if - interface control information. 689 * struct brcmf_if - interface control information.
687 * 690 *
688 * @drvr: points to device related information. 691 * @drvr: points to device related information.
692 * @vif: points to cfg80211 specific interface information.
689 * @ndev: associated network device. 693 * @ndev: associated network device.
690 * @stats: interface specific network statistics. 694 * @stats: interface specific network statistics.
691 * @idx: interface index in device firmware. 695 * @idx: interface index in device firmware.
@@ -694,6 +698,7 @@ struct brcmf_if_event {
694 */ 698 */
695struct brcmf_if { 699struct brcmf_if {
696 struct brcmf_pub *drvr; 700 struct brcmf_pub *drvr;
701 struct brcmf_cfg80211_vif *vif;
697 struct net_device *ndev; 702 struct net_device *ndev;
698 struct net_device_stats stats; 703 struct net_device_stats stats;
699 int idx; 704 int idx;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 069a4e468120..21d6ab358c81 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
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 191262578e02..6644ea85f07f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -235,6 +235,25 @@ struct brcmf_cfg80211_profile {
235 s32 band; 235 s32 band;
236}; 236};
237 237
238/**
239 * struct brcmf_cfg80211_vif - virtual interface specific information.
240 *
241 * @ifp: lower layer interface pointer
242 * @wdev: wireless device.
243 * @mode: operating mode.
244 * @roam_off: roaming state.
245 * @pm_block: power-management blocked.
246 * @list: linked list.
247 */
248struct brcmf_cfg80211_vif {
249 struct brcmf_if *ifp;
250 struct wireless_dev wdev;
251 s32 mode;
252 s32 roam_off;
253 bool pm_block;
254 struct list_head list;
255};
256
238/* dongle iscan event loop */ 257/* dongle iscan event loop */
239struct brcmf_cfg80211_iscan_eloop { 258struct brcmf_cfg80211_iscan_eloop {
240 s32 (*handler[WL_SCAN_ERSULTS_LAST]) 259 s32 (*handler[WL_SCAN_ERSULTS_LAST])
@@ -383,7 +402,7 @@ struct brcmf_pno_scanresults_le {
383/** 402/**
384 * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface 403 * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
385 * 404 *
386 * @wdev: representing wl cfg80211 device. 405 * @wiphy: wiphy object for cfg80211 interface.
387 * @conf: dongle configuration. 406 * @conf: dongle configuration.
388 * @scan_request: cfg80211 scan request object. 407 * @scan_request: cfg80211 scan request object.
389 * @el: main event loop. 408 * @el: main event loop.
@@ -422,10 +441,11 @@ struct brcmf_pno_scanresults_le {
422 * @escan_timeout_work: scan timeout worker. 441 * @escan_timeout_work: scan timeout worker.
423 * @escan_ioctl_buf: dongle command buffer for escan commands. 442 * @escan_ioctl_buf: dongle command buffer for escan commands.
424 * @ap_info: host ap information. 443 * @ap_info: host ap information.
425 * @ci: used to link this structure to netdev private data. 444 * @vif_list: linked list of vif instances.
445 * @vif_cnt: number of vif instances.
426 */ 446 */
427struct brcmf_cfg80211_info { 447struct brcmf_cfg80211_info {
428 struct wireless_dev *wdev; 448 struct wiphy *wiphy;
429 struct brcmf_cfg80211_conf *conf; 449 struct brcmf_cfg80211_conf *conf;
430 struct cfg80211_scan_request *scan_request; 450 struct cfg80211_scan_request *scan_request;
431 struct brcmf_cfg80211_event_loop el; 451 struct brcmf_cfg80211_event_loop el;
@@ -464,11 +484,13 @@ struct brcmf_cfg80211_info {
464 struct work_struct escan_timeout_work; 484 struct work_struct escan_timeout_work;
465 u8 *escan_ioctl_buf; 485 u8 *escan_ioctl_buf;
466 struct ap_info *ap_info; 486 struct ap_info *ap_info;
487 struct list_head vif_list;
488 u8 vif_cnt;
467}; 489};
468 490
469static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *w) 491static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
470{ 492{
471 return w->wdev->wiphy; 493 return cfg->wiphy;
472} 494}
473 495
474static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w) 496static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
@@ -481,9 +503,12 @@ static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd)
481 return (struct brcmf_cfg80211_info *)(wdev_priv(wd)); 503 return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
482} 504}
483 505
484static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg) 506static inline
507struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
485{ 508{
486 return cfg->wdev->netdev; 509 struct brcmf_cfg80211_vif *vif;
510 vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list);
511 return vif->wdev.netdev;
487} 512}
488 513
489static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev) 514static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)