Commit d6bffe8b authored by Avinash Patil's avatar Avinash Patil Committed by John W. Linville

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: default avatarAvinash Patil <patila@marvell.com>
Signed-off-by: default avatarYogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarKiran Divekar <dkiran@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 03785387
...@@ -1287,6 +1287,7 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, ...@@ -1287,6 +1287,7 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
struct mwifiex_adapter *adapter; struct mwifiex_adapter *adapter;
struct net_device *dev; struct net_device *dev;
void *mdev_priv; void *mdev_priv;
struct wireless_dev *wdev;
if (!priv) if (!priv)
return NULL; return NULL;
...@@ -1299,12 +1300,21 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, ...@@ -1299,12 +1300,21 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
if (priv->bss_mode) { if (priv->bss_mode) {
wiphy_err(wiphy, "cannot create multiple" wiphy_err(wiphy,
" station/adhoc interfaces\n"); "cannot create multiple sta/adhoc ifaces\n");
return NULL; 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) if (type == NL80211_IFTYPE_UNSPECIFIED)
priv->bss_mode = NL80211_IFTYPE_STATION; priv->bss_mode = NL80211_IFTYPE_STATION;
else else
...@@ -1312,10 +1322,35 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, ...@@ -1312,10 +1322,35 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_type = MWIFIEX_BSS_TYPE_STA; priv->bss_type = MWIFIEX_BSS_TYPE_STA;
priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; 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_role = MWIFIEX_BSS_ROLE_STA;
priv->bss_num = 0; 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; break;
default: default:
wiphy_err(wiphy, "type not supported\n"); wiphy_err(wiphy, "type not supported\n");
...@@ -1329,6 +1364,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, ...@@ -1329,6 +1364,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
goto error; 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_net_set(dev, wiphy_net(wiphy));
dev->ieee80211_ptr = priv->wdev; dev->ieee80211_ptr = priv->wdev;
dev->ieee80211_ptr->iftype = priv->bss_mode; dev->ieee80211_ptr->iftype = priv->bss_mode;
...@@ -1343,9 +1387,6 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, ...@@ -1343,9 +1387,6 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
mdev_priv = netdev_priv(dev); mdev_priv = netdev_priv(dev);
*((unsigned long *) mdev_priv) = (unsigned long) priv; *((unsigned long *) mdev_priv) = (unsigned long) priv;
priv->netdev = dev;
mwifiex_init_priv_params(priv, dev);
SET_NETDEV_DEV(dev, adapter->dev); SET_NETDEV_DEV(dev, adapter->dev);
/* Register network device */ /* Register network device */
...@@ -1436,82 +1477,65 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { ...@@ -1436,82 +1477,65 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
* default parameters and handler function pointers, and finally * default parameters and handler function pointers, and finally
* registers the device. * registers the device.
*/ */
int mwifiex_register_cfg80211(struct mwifiex_private *priv)
int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
{ {
int ret; int ret;
void *wdev_priv; void *wdev_priv;
struct wireless_dev *wdev; struct wiphy *wiphy;
struct ieee80211_sta_ht_cap *ht_info; struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
u8 *country_code; u8 *country_code;
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); /* create a new wiphy for use with cfg80211 */
if (!wdev) { wiphy = wiphy_new(&mwifiex_cfg80211_ops,
dev_err(priv->adapter->dev, "%s: allocating wireless device\n", sizeof(struct mwifiex_adapter *));
__func__); if (!wiphy) {
return -ENOMEM; dev_err(adapter->dev, "%s: creating new wiphy\n", __func__);
}
wdev->wiphy =
wiphy_new(&mwifiex_cfg80211_ops,
sizeof(struct mwifiex_private *));
if (!wdev->wiphy) {
kfree(wdev);
return -ENOMEM; return -ENOMEM;
} }
wdev->iftype = NL80211_IFTYPE_STATION; wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
wdev->wiphy->max_scan_ssids = 10; wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
wdev->wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_ADHOC); BIT(NL80211_IFTYPE_AP);
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
ht_info = &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap; if (adapter->config_bands & BAND_A)
mwifiex_setup_ht_caps(ht_info, priv); wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
else
if (priv->adapter->config_bands & BAND_A) { wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
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;
}
/* Initialize cipher suits */ /* Initialize cipher suits */
wdev->wiphy->cipher_suites = mwifiex_cipher_suites; wiphy->cipher_suites = mwifiex_cipher_suites;
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 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 */ /* 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 */ /* 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; *(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) { if (ret < 0) {
dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", dev_err(adapter->dev,
__func__); "%s: wiphy_register failed: %d\n", __func__, ret);
wiphy_free(wdev->wiphy); wiphy_free(wiphy);
kfree(wdev);
return ret; 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); country_code = mwifiex_11d_code_2_region(priv->adapter->region_code);
if (country_code && regulatory_hint(wdev->wiphy, country_code)) if (country_code && regulatory_hint(wiphy, country_code))
dev_err(priv->adapter->dev, dev_err(adapter->dev, "regulatory_hint() failed\n");
"%s: regulatory_hint failed\n", __func__);
priv->wdev = wdev;
adapter->wiphy = wiphy;
return ret; return ret;
} }
...@@ -24,6 +24,6 @@ ...@@ -24,6 +24,6 @@
#include "main.h" #include "main.h"
int mwifiex_register_cfg80211(struct mwifiex_private *); int mwifiex_register_cfg80211(struct mwifiex_adapter *);
#endif #endif
...@@ -349,19 +349,26 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) ...@@ -349,19 +349,26 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
goto done; goto done;
priv = adapter->priv[0]; priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
if (mwifiex_register_cfg80211(priv) != 0) { if (mwifiex_register_cfg80211(adapter)) {
dev_err(adapter->dev, "cannot register with cfg80211\n"); dev_err(adapter->dev, "cannot register with cfg80211\n");
goto err_init_fw; goto err_init_fw;
} }
rtnl_lock(); rtnl_lock();
/* Create station interface by default */ /* 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)) { NL80211_IFTYPE_STATION, NULL, NULL)) {
dev_err(adapter->dev, "cannot create default STA interface\n"); dev_err(adapter->dev, "cannot create default STA interface\n");
goto err_add_intf; 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(); rtnl_unlock();
mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); 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) ...@@ -369,7 +376,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
goto done; goto done;
err_add_intf: err_add_intf:
mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
rtnl_unlock(); rtnl_unlock();
err_init_fw: err_init_fw:
pr_debug("info: %s: unregister device\n", __func__); pr_debug("info: %s: unregister device\n", __func__);
...@@ -830,8 +837,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) ...@@ -830,8 +837,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
rtnl_lock(); rtnl_lock();
if (priv->wdev && priv->netdev) if (priv->wdev && priv->netdev)
mwifiex_del_virtual_intf(priv->wdev->wiphy, mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
priv->netdev);
rtnl_unlock(); rtnl_unlock();
} }
......
...@@ -370,6 +370,7 @@ struct mwifiex_private { ...@@ -370,6 +370,7 @@ struct mwifiex_private {
u8 bss_role; u8 bss_role;
u8 bss_priority; u8 bss_priority;
u8 bss_num; u8 bss_num;
u8 bss_started;
u8 frame_type; u8 frame_type;
u8 curr_addr[ETH_ALEN]; u8 curr_addr[ETH_ALEN];
u8 media_connected; u8 media_connected;
...@@ -571,6 +572,7 @@ struct mwifiex_adapter { ...@@ -571,6 +572,7 @@ struct mwifiex_adapter {
char fw_name[32]; char fw_name[32];
int winner; int winner;
struct device *dev; struct device *dev;
struct wiphy *wiphy;
bool surprise_removed; bool surprise_removed;
u32 fw_release_number; u32 fw_release_number;
u16 init_wait_q_woken; u16 init_wait_q_woken;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment