static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
struct wireless_dev *wdev)
{
- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = wdev->netdev;
struct brcmf_if *ifp = netdev_priv(ndev);
int ret;
static
int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
{
- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct net_device *ndev = wdev->netdev;
if (ndev && ndev == cfg_to_ndev(cfg))
enum nl80211_iftype type,
struct vif_params *params)
{
- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_vif *vif = ifp->vif;
s32 infra = 0;
brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
s32 *dbm)
{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct net_device *ndev = cfg_to_ndev(cfg);
- struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev);
s32 qdbm = 0;
s32 err;
brcmf_dbg(TRACE, "Enter\n");
- if (!check_vif_up(ifp->vif))
+ if (!check_vif_up(vif))
return -EIO;
- err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &qdbm);
+ err = brcmf_fil_iovar_int_get(vif->ifp, "qtxpower", &qdbm);
if (err) {
brcmf_err("error (%d)\n", err);
goto done;
struct cfg80211_sched_scan_request *req)
{
struct brcmf_if *ifp = netdev_priv(ndev);
- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
brcmf_dbg(SCAN, "Enter: n_match_sets=%d n_ssids=%d\n",
req->n_match_sets, req->n_ssids);
.del_pmk = brcmf_cfg80211_del_pmk,
};
+struct cfg80211_ops *brcmf_cfg80211_get_ops(void)
+{
+ return kmemdup(&brcmf_cfg80211_ops, sizeof(brcmf_cfg80211_ops),
+ GFP_KERNEL);
+}
+
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
enum nl80211_iftype type)
{
static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
u32 bw_cap[])
{
- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
struct ieee80211_supported_band *band;
struct ieee80211_channel *channel;
struct wiphy *wiphy;
static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
{
- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
struct ieee80211_supported_band *band;
struct brcmf_fil_bwcap_le band_bwcap;
struct brcmf_chanspec_list *list;
}
}
-static int brcmf_setup_wiphybands(struct wiphy *wiphy)
+static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)
{
- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+ struct wiphy *wiphy;
u32 nmode = 0;
u32 vhtmode = 0;
u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *req)
{
- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
struct brcmf_fil_country_le ccreq;
s32 err;
int i;
brcmf_err("Firmware rejected country setting\n");
return;
}
- brcmf_setup_wiphybands(wiphy);
+ brcmf_setup_wiphybands(cfg);
}
static void brcmf_free_wiphy(struct wiphy *wiphy)
if (wiphy->wowlan != &brcmf_wowlan_support)
kfree(wiphy->wowlan);
#endif
- wiphy_free(wiphy);
}
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
- struct device *busdev,
+ struct cfg80211_ops *ops,
bool p2pdev_forced)
{
+ struct wiphy *wiphy = drvr->wiphy;
struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
struct brcmf_cfg80211_info *cfg;
- struct wiphy *wiphy;
- struct cfg80211_ops *ops;
struct brcmf_cfg80211_vif *vif;
struct brcmf_if *ifp;
s32 err = 0;
return NULL;
}
- ops = kmemdup(&brcmf_cfg80211_ops, sizeof(*ops), GFP_KERNEL);
- if (!ops)
- return NULL;
-
- ifp = netdev_priv(ndev);
-#ifdef CONFIG_PM
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
- ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
-#endif
- wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info));
- if (!wiphy) {
+ cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+ if (!cfg) {
brcmf_err("Could not allocate wiphy device\n");
- goto ops_out;
+ return NULL;
}
- memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
- set_wiphy_dev(wiphy, busdev);
- cfg = wiphy_priv(wiphy);
cfg->wiphy = wiphy;
- cfg->ops = ops;
cfg->pub = drvr;
init_vif_event(&cfg->vif_event);
INIT_LIST_HEAD(&cfg->vif_list);
if (IS_ERR(vif))
goto wiphy_out;
+ ifp = netdev_priv(ndev);
vif->ifp = ifp;
vif->wdev.netdev = ndev;
ndev->ieee80211_ptr = &vif->wdev;
if (err < 0)
goto priv_out;
+ /* regulatory notifer below needs access to cfg so
+ * assign it now.
+ */
+ drvr->config = cfg;
+
brcmf_dbg(INFO, "Registering custom regulatory\n");
wiphy->reg_notifier = brcmf_cfg80211_reg_notifier;
wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap;
*cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
}
+#ifdef CONFIG_PM
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
+ ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
+#endif
err = wiphy_register(wiphy);
if (err < 0) {
brcmf_err("Could not register wiphy device (%d)\n", err);
goto priv_out;
}
- err = brcmf_setup_wiphybands(wiphy);
+ err = brcmf_setup_wiphybands(cfg);
if (err) {
brcmf_err("Setting wiphy bands failed (%d)\n", err);
goto wiphy_unreg_out;
else
*cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
}
- /* p2p might require that "if-events" get processed by fweh. So
- * activate the already registered event handlers now and activate
- * the rest when initialization has completed. drvr->config needs to
- * be assigned before activating events.
- */
- drvr->config = cfg;
+
err = brcmf_fweh_activate_events(ifp);
if (err) {
brcmf_err("FWEH activation failed (%d)\n", err);
ifp->vif = NULL;
wiphy_out:
brcmf_free_wiphy(wiphy);
-ops_out:
- kfree(ops);
+ kfree(cfg);
return NULL;
}
kfree(cfg->ops);
wl_deinit_priv(cfg);
brcmf_free_wiphy(cfg->wiphy);
+ kfree(cfg);
}
static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
{
- return (struct brcmf_cfg80211_info *)(wiphy_priv(w));
+ struct brcmf_pub *drvr = wiphy_priv(w);
+ return drvr->config;
}
static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd)
{
- return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
+ return wiphy_to_cfg(wd->wiphy);
+}
+
+static inline struct brcmf_cfg80211_vif *wdev_to_vif(struct wireless_dev *wdev)
+{
+ return container_of(wdev, struct brcmf_cfg80211_vif, wdev);
}
static inline
struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
{
- struct brcmf_cfg80211_vif *vif;
- vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list);
- return vif->wdev.netdev;
+ return brcmf_get_ifp(cfg->pub, 0)->ndev;
}
static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
}
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
- struct device *busdev,
+ struct cfg80211_ops *ops,
bool p2pdev_forced);
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
s32 brcmf_cfg80211_up(struct net_device *ndev);
s32 brcmf_cfg80211_down(struct net_device *ndev);
+struct cfg80211_ops *brcmf_cfg80211_get_ops(void);
enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
return 0;
}
-static int brcmf_bus_started(struct brcmf_pub *drvr)
+static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
{
int ret = -1;
struct brcmf_bus *bus_if = drvr->bus_if;
brcmf_proto_add_if(drvr, ifp);
- drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev,
+ drvr->config = brcmf_cfg80211_attach(drvr, ops,
drvr->settings->p2p_enable);
if (drvr->config == NULL) {
ret = -ENOMEM;
int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
{
+ struct wiphy *wiphy;
+ struct cfg80211_ops *ops;
struct brcmf_pub *drvr = NULL;
int ret = 0;
int i;
brcmf_dbg(TRACE, "Enter\n");
- /* Allocate primary brcmf_info */
- drvr = kzalloc(sizeof(*drvr), GFP_ATOMIC);
- if (!drvr)
+ ops = brcmf_cfg80211_get_ops();
+ if (!ops)
return -ENOMEM;
+ wiphy = wiphy_new(ops, sizeof(*drvr));
+ if (!wiphy)
+ return -ENOMEM;
+
+ set_wiphy_dev(wiphy, dev);
+ drvr = wiphy_priv(wiphy);
+ drvr->wiphy = wiphy;
+
for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
/* attach firmware event handler */
brcmf_fweh_attach(drvr);
- ret = brcmf_bus_started(drvr);
+ ret = brcmf_bus_started(drvr, ops);
if (ret != 0) {
brcmf_err("dongle is not responding: err=%d\n", ret);
goto fail;
}
+
+ drvr->config->ops = ops;
return 0;
fail:
brcmf_detach(dev);
+ kfree(ops);
return ret;
}
brcmf_remove_interface(drvr->iflist[i], false);
brcmf_cfg80211_detach(drvr->config);
+ drvr->config = NULL;
brcmf_bus_stop(drvr->bus_if);
brcmf_debug_detach(drvr);
bus_if->drvr = NULL;
- kfree(drvr);
+ wiphy_free(drvr->wiphy);
}
s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len)