mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-10 19:35:21 +02:00
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>
This commit is contained in:
parent
03785387e1
commit
d6bffe8bb5
|
@ -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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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 = {
|
||||||
* 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) {
|
||||||
|
dev_err(adapter->dev, "%s: creating new wiphy\n", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
wdev->wiphy =
|
wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
|
||||||
wiphy_new(&mwifiex_cfg80211_ops,
|
wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
|
||||||
sizeof(struct mwifiex_private *));
|
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||||
if (!wdev->wiphy) {
|
BIT(NL80211_IFTYPE_ADHOC) |
|
||||||
kfree(wdev);
|
BIT(NL80211_IFTYPE_AP);
|
||||||
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;
|
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 @@
|
||||||
|
|
||||||
#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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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 {
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user