summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2012-05-08 18:30:15 -0700
committerJohn W. Linville <linville@tuxdriver.com>2012-05-16 12:46:34 -0400
commitd6bffe8bb520bc1ce3333d05ce67f36dab9a61aa (patch)
treece098372b8453a433ac5b27aa7136f16d12d6915 /drivers/net/wireless
parent03785387e1c6b236a04d595f98b014b78e585202 (diff)
downloadlinux-d6bffe8bb520bc1ce3333d05ce67f36dab9a61aa.tar.gz
linux-d6bffe8bb520bc1ce3333d05ce67f36dab9a61aa.tar.bz2
linux-d6bffe8bb520bc1ce3333d05ce67f36dab9a61aa.zip
mwifiex: support for creation of AP interface
1. wiphy structure is per device; hence moved it to mwifiex_adapter mwifiex_register_cfg80211 takes mwifiex_adapter as parameter. This function only registers wiphy with cfg80211. 2. Creation of interfaces is moved to cfg80211 add_virtual_interface handler. 3. Create 2 interfaces by default: station and AP Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Kiran Divekar <dkiran@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c142
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.h2
-rw-r--r--drivers/net/wireless/mwifiex/main.c18
-rw-r--r--drivers/net/wireless/mwifiex/main.h2
4 files changed, 98 insertions, 66 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index c78ea873a63a..38d51910d13c 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1287,6 +1287,7 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
struct mwifiex_adapter *adapter;
struct net_device *dev;
void *mdev_priv;
+ struct wireless_dev *wdev;
if (!priv)
return NULL;
@@ -1299,12 +1300,21 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
+ priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
if (priv->bss_mode) {
- wiphy_err(wiphy, "cannot create multiple"
- " station/adhoc interfaces\n");
+ wiphy_err(wiphy,
+ "cannot create multiple sta/adhoc ifaces\n");
return NULL;
}
+ wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+ if (!wdev)
+ return NULL;
+
+ wdev->wiphy = wiphy;
+ priv->wdev = wdev;
+ wdev->iftype = NL80211_IFTYPE_STATION;
+
if (type == NL80211_IFTYPE_UNSPECIFIED)
priv->bss_mode = NL80211_IFTYPE_STATION;
else
@@ -1312,11 +1322,36 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_type = MWIFIEX_BSS_TYPE_STA;
priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
- priv->bss_priority = 0;
+ priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
priv->bss_num = 0;
break;
+ case NL80211_IFTYPE_AP:
+ priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP];
+
+ if (priv->bss_mode) {
+ wiphy_err(wiphy, "Can't create multiple AP interfaces");
+ return NULL;
+ }
+
+ wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+ if (!wdev)
+ return NULL;
+
+ priv->wdev = wdev;
+ wdev->wiphy = wiphy;
+ wdev->iftype = NL80211_IFTYPE_AP;
+
+ priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
+ priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
+ priv->bss_priority = MWIFIEX_BSS_ROLE_UAP;
+ priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
+ priv->bss_started = 0;
+ priv->bss_num = 0;
+ priv->bss_mode = type;
+
+ break;
default:
wiphy_err(wiphy, "type not supported\n");
return NULL;
@@ -1329,6 +1364,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
goto error;
}
+ mwifiex_init_priv_params(priv, dev);
+ priv->netdev = dev;
+
+ mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
+
+ if (adapter->config_bands & BAND_A)
+ mwifiex_setup_ht_caps(
+ &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
+
dev_net_set(dev, wiphy_net(wiphy));
dev->ieee80211_ptr = priv->wdev;
dev->ieee80211_ptr->iftype = priv->bss_mode;
@@ -1343,9 +1387,6 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
mdev_priv = netdev_priv(dev);
*((unsigned long *) mdev_priv) = (unsigned long) priv;
- priv->netdev = dev;
- mwifiex_init_priv_params(priv, dev);
-
SET_NETDEV_DEV(dev, adapter->dev);
/* Register network device */
@@ -1436,82 +1477,65 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
* default parameters and handler function pointers, and finally
* registers the device.
*/
-int mwifiex_register_cfg80211(struct mwifiex_private *priv)
+
+int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
{
int ret;
void *wdev_priv;
- struct wireless_dev *wdev;
- struct ieee80211_sta_ht_cap *ht_info;
+ struct wiphy *wiphy;
+ struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
u8 *country_code;
- wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
- if (!wdev) {
- dev_err(priv->adapter->dev, "%s: allocating wireless device\n",
- __func__);
+ /* create a new wiphy for use with cfg80211 */
+ wiphy = wiphy_new(&mwifiex_cfg80211_ops,
+ sizeof(struct mwifiex_adapter *));
+ if (!wiphy) {
+ dev_err(adapter->dev, "%s: creating new wiphy\n", __func__);
return -ENOMEM;
}
- wdev->wiphy =
- wiphy_new(&mwifiex_cfg80211_ops,
- sizeof(struct mwifiex_private *));
- if (!wdev->wiphy) {
- kfree(wdev);
- return -ENOMEM;
- }
- wdev->iftype = NL80211_IFTYPE_STATION;
- wdev->wiphy->max_scan_ssids = 10;
- wdev->wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
- wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
-
- wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
- ht_info = &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap;
- mwifiex_setup_ht_caps(ht_info, priv);
-
- if (priv->adapter->config_bands & BAND_A) {
- wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
- ht_info = &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap;
- mwifiex_setup_ht_caps(ht_info, priv);
- } else {
- wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
- }
+ wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
+ wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP);
+
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
+ if (adapter->config_bands & BAND_A)
+ wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
+ else
+ wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
/* Initialize cipher suits */
- wdev->wiphy->cipher_suites = mwifiex_cipher_suites;
- wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
+ wiphy->cipher_suites = mwifiex_cipher_suites;
+ wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
- memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
- wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_CUSTOM_REGULATORY;
/* Reserve space for mwifiex specific private data for BSS */
- wdev->wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
+ wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
- wdev->wiphy->reg_notifier = mwifiex_reg_notifier;
+ wiphy->reg_notifier = mwifiex_reg_notifier;
/* Set struct mwifiex_private pointer in wiphy_priv */
- wdev_priv = wiphy_priv(wdev->wiphy);
+ wdev_priv = wiphy_priv(wiphy);
*(unsigned long *) wdev_priv = (unsigned long) priv;
- set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev);
+ set_wiphy_dev(wiphy, (struct device *)priv->adapter->dev);
- ret = wiphy_register(wdev->wiphy);
+ ret = wiphy_register(wiphy);
if (ret < 0) {
- dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n",
- __func__);
- wiphy_free(wdev->wiphy);
- kfree(wdev);
+ dev_err(adapter->dev,
+ "%s: wiphy_register failed: %d\n", __func__, ret);
+ wiphy_free(wiphy);
return ret;
- } else {
- dev_dbg(priv->adapter->dev,
- "info: successfully registered wiphy device\n");
}
-
country_code = mwifiex_11d_code_2_region(priv->adapter->region_code);
- if (country_code && regulatory_hint(wdev->wiphy, country_code))
- dev_err(priv->adapter->dev,
- "%s: regulatory_hint failed\n", __func__);
-
- priv->wdev = wdev;
+ if (country_code && regulatory_hint(wiphy, country_code))
+ dev_err(adapter->dev, "regulatory_hint() failed\n");
+ adapter->wiphy = wiphy;
return ret;
}
diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h
index 76c76c60438b..c5848934f111 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.h
+++ b/drivers/net/wireless/mwifiex/cfg80211.h
@@ -24,6 +24,6 @@
#include "main.h"
-int mwifiex_register_cfg80211(struct mwifiex_private *);
+int mwifiex_register_cfg80211(struct mwifiex_adapter *);
#endif
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 5ac0059890b0..43e4efad4cf7 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -349,19 +349,26 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
goto done;
- priv = adapter->priv[0];
- if (mwifiex_register_cfg80211(priv) != 0) {
+ priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
+ if (mwifiex_register_cfg80211(adapter)) {
dev_err(adapter->dev, "cannot register with cfg80211\n");
goto err_init_fw;
}
rtnl_lock();
/* Create station interface by default */
- if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d",
+ if (!mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d",
NL80211_IFTYPE_STATION, NULL, NULL)) {
dev_err(adapter->dev, "cannot create default STA interface\n");
goto err_add_intf;
}
+
+ /* Create AP interface by default */
+ if (!mwifiex_add_virtual_intf(adapter->wiphy, "uap%d",
+ NL80211_IFTYPE_AP, NULL, NULL)) {
+ dev_err(adapter->dev, "cannot create default AP interface\n");
+ goto err_add_intf;
+ }
rtnl_unlock();
mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
@@ -369,7 +376,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
goto done;
err_add_intf:
- mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
+ mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
rtnl_unlock();
err_init_fw:
pr_debug("info: %s: unregister device\n", __func__);
@@ -830,8 +837,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
rtnl_lock();
if (priv->wdev && priv->netdev)
- mwifiex_del_virtual_intf(priv->wdev->wiphy,
- priv->netdev);
+ mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
rtnl_unlock();
}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 324ad390cacd..9fc22427b33f 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -370,6 +370,7 @@ struct mwifiex_private {
u8 bss_role;
u8 bss_priority;
u8 bss_num;
+ u8 bss_started;
u8 frame_type;
u8 curr_addr[ETH_ALEN];
u8 media_connected;
@@ -571,6 +572,7 @@ struct mwifiex_adapter {
char fw_name[32];
int winner;
struct device *dev;
+ struct wiphy *wiphy;
bool surprise_removed;
u32 fw_release_number;
u16 init_wait_q_woken;