forked from Minki/linux
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>
This commit is contained in:
parent
ec6de0ed3e
commit
3eacf86655
@ -682,10 +682,14 @@ struct brcmf_if_event {
|
||||
u8 bssidx;
|
||||
};
|
||||
|
||||
/* forward declaration */
|
||||
struct brcmf_cfg80211_vif;
|
||||
|
||||
/**
|
||||
* struct brcmf_if - interface control information.
|
||||
*
|
||||
* @drvr: points to device related information.
|
||||
* @vif: points to cfg80211 specific interface information.
|
||||
* @ndev: associated network device.
|
||||
* @stats: interface specific network statistics.
|
||||
* @idx: interface index in device firmware.
|
||||
@ -694,6 +698,7 @@ struct brcmf_if_event {
|
||||
*/
|
||||
struct brcmf_if {
|
||||
struct brcmf_pub *drvr;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
struct net_device *ndev;
|
||||
struct net_device_stats stats;
|
||||
int idx;
|
||||
|
@ -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;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
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) |
|
||||
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);
|
||||
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
|
||||
wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
|
||||
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;
|
||||
}
|
||||
return wdev;
|
||||
|
||||
wiphy_register_out:
|
||||
wiphy_free(wdev->wiphy);
|
||||
|
||||
wiphy_new_out:
|
||||
kfree(wdev);
|
||||
|
||||
wiphy_free(wiphy);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
return wiphy;
|
||||
}
|
||||
|
||||
static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg)
|
||||
static
|
||||
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *netdev,
|
||||
s32 mode, bool pm_block)
|
||||
{
|
||||
struct wireless_dev *wdev = cfg->wdev;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
|
||||
if (!wdev) {
|
||||
WL_ERR("wdev is invalid\n");
|
||||
return;
|
||||
if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
|
||||
return ERR_PTR(-ENOSPC);
|
||||
|
||||
vif = kzalloc(sizeof(*vif), GFP_KERNEL);
|
||||
if (!vif)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
vif->wdev.wiphy = cfg->wiphy;
|
||||
vif->wdev.netdev = netdev;
|
||||
vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode);
|
||||
|
||||
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;
|
||||
|
||||
list_add_tail(&vif->list, &cfg->vif_list);
|
||||
cfg->vif_cnt++;
|
||||
return vif;
|
||||
}
|
||||
|
||||
static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
struct wiphy *wiphy;
|
||||
|
||||
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;
|
||||
|
||||
cfg = wiphy_priv(wiphy);
|
||||
cfg->wiphy = wiphy;
|
||||
cfg->pub = drvr;
|
||||
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;
|
||||
}
|
||||
|
||||
wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
|
||||
cfg = wdev_to_cfg(wdev);
|
||||
cfg->wdev = wdev;
|
||||
cfg->pub = drvr;
|
||||
ndev->ieee80211_ptr = wdev;
|
||||
SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
|
||||
wdev->netdev = ndev;
|
||||
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
|
||||
|
@ -235,6 +235,25 @@ struct brcmf_cfg80211_profile {
|
||||
s32 band;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_vif - virtual interface specific information.
|
||||
*
|
||||
* @ifp: lower layer interface pointer
|
||||
* @wdev: wireless device.
|
||||
* @mode: operating mode.
|
||||
* @roam_off: roaming state.
|
||||
* @pm_block: power-management blocked.
|
||||
* @list: linked list.
|
||||
*/
|
||||
struct brcmf_cfg80211_vif {
|
||||
struct brcmf_if *ifp;
|
||||
struct wireless_dev wdev;
|
||||
s32 mode;
|
||||
s32 roam_off;
|
||||
bool pm_block;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/* dongle iscan event loop */
|
||||
struct brcmf_cfg80211_iscan_eloop {
|
||||
s32 (*handler[WL_SCAN_ERSULTS_LAST])
|
||||
@ -383,7 +402,7 @@ struct brcmf_pno_scanresults_le {
|
||||
/**
|
||||
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
|
||||
*
|
||||
* @wdev: representing wl cfg80211 device.
|
||||
* @wiphy: wiphy object for cfg80211 interface.
|
||||
* @conf: dongle configuration.
|
||||
* @scan_request: cfg80211 scan request object.
|
||||
* @el: main event loop.
|
||||
@ -422,10 +441,11 @@ struct brcmf_pno_scanresults_le {
|
||||
* @escan_timeout_work: scan timeout worker.
|
||||
* @escan_ioctl_buf: dongle command buffer for escan commands.
|
||||
* @ap_info: host ap information.
|
||||
* @ci: used to link this structure to netdev private data.
|
||||
* @vif_list: linked list of vif instances.
|
||||
* @vif_cnt: number of vif instances.
|
||||
*/
|
||||
struct brcmf_cfg80211_info {
|
||||
struct wireless_dev *wdev;
|
||||
struct wiphy *wiphy;
|
||||
struct brcmf_cfg80211_conf *conf;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct brcmf_cfg80211_event_loop el;
|
||||
@ -464,11 +484,13 @@ struct brcmf_cfg80211_info {
|
||||
struct work_struct escan_timeout_work;
|
||||
u8 *escan_ioctl_buf;
|
||||
struct ap_info *ap_info;
|
||||
struct list_head vif_list;
|
||||
u8 vif_cnt;
|
||||
};
|
||||
|
||||
static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *w)
|
||||
static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
return w->wdev->wiphy;
|
||||
return cfg->wiphy;
|
||||
}
|
||||
|
||||
static 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)
|
||||
return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
|
||||
}
|
||||
|
||||
static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
|
||||
static inline
|
||||
struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
return cfg->wdev->netdev;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list);
|
||||
return vif->wdev.netdev;
|
||||
}
|
||||
|
||||
static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
|
||||
|
Loading…
Reference in New Issue
Block a user