Commit cf052335 authored by Avinash Patil's avatar Avinash Patil Committed by Kalle Valo

mwifiex: manage virtual interface limits efficiently

Currently interface limits are checked by seeing if bss_mode for
particular priv is set. If bss_mode is not set, interface creation
is allowed. This patch adds framework to initializes maximum virtual
interfaces supported during load time and check current number of
interfaces created agains allowed interface limit during new virtual
interface creation.
Signed-off-by: default avatarAvinash Patil <patila@marvell.com>
Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarCathy Luo <cluo@marvell.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 1247cc1f
...@@ -2185,13 +2185,20 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, ...@@ -2185,13 +2185,20 @@ struct wireless_dev *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 (adapter->curr_iface_comb.sta_intf ==
if (priv->bss_mode) { adapter->iface_limit.sta_intf) {
wiphy_err(wiphy, wiphy_err(wiphy,
"cannot create multiple sta/adhoc ifaces\n"); "cannot create multiple sta/adhoc ifaces\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
priv = mwifiex_get_unused_priv(adapter);
if (!priv) {
wiphy_err(wiphy,
"could not get free private struct\n");
return ERR_PTR(-EFAULT);
}
priv->wdev.wiphy = wiphy; priv->wdev.wiphy = wiphy;
priv->wdev.iftype = NL80211_IFTYPE_STATION; priv->wdev.iftype = NL80211_IFTYPE_STATION;
...@@ -2208,13 +2215,20 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, ...@@ -2208,13 +2215,20 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
break; break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP]; if (adapter->curr_iface_comb.uap_intf ==
adapter->iface_limit.uap_intf) {
if (priv->bss_mode) { wiphy_err(wiphy,
wiphy_err(wiphy, "Can't create multiple AP interfaces"); "cannot create multiple AP ifaces\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
priv = mwifiex_get_unused_priv(adapter);
if (!priv) {
wiphy_err(wiphy,
"could not get free private struct\n");
return ERR_PTR(-EFAULT);
}
priv->wdev.wiphy = wiphy; priv->wdev.wiphy = wiphy;
priv->wdev.iftype = NL80211_IFTYPE_AP; priv->wdev.iftype = NL80211_IFTYPE_AP;
...@@ -2228,15 +2242,21 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, ...@@ -2228,15 +2242,21 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
break; break;
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
priv = adapter->priv[MWIFIEX_BSS_TYPE_P2P]; if (adapter->curr_iface_comb.p2p_intf ==
adapter->iface_limit.p2p_intf) {
if (priv->bss_mode) { wiphy_err(wiphy,
wiphy_err(wiphy, "Can't create multiple P2P ifaces"); "cannot create multiple P2P ifaces\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
priv->wdev.wiphy = wiphy; priv = mwifiex_get_unused_priv(adapter);
if (!priv) {
wiphy_err(wiphy,
"could not get free private struct\n");
return ERR_PTR(-EFAULT);
}
priv->wdev.wiphy = wiphy;
/* At start-up, wpa_supplicant tries to change the interface /* At start-up, wpa_supplicant tries to change the interface
* to NL80211_IFTYPE_STATION if it is not managed mode. * to NL80211_IFTYPE_STATION if it is not managed mode.
*/ */
...@@ -2329,6 +2349,23 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, ...@@ -2329,6 +2349,23 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
mwifiex_dev_debugfs_init(priv); mwifiex_dev_debugfs_init(priv);
#endif #endif
switch (type) {
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
adapter->curr_iface_comb.sta_intf++;
break;
case NL80211_IFTYPE_AP:
adapter->curr_iface_comb.uap_intf++;
break;
case NL80211_IFTYPE_P2P_CLIENT:
adapter->curr_iface_comb.p2p_intf++;
break;
default:
wiphy_err(wiphy, "type not supported\n");
return ERR_PTR(-EINVAL);
}
return &priv->wdev; return &priv->wdev;
} }
EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
...@@ -2339,12 +2376,13 @@ EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); ...@@ -2339,12 +2376,13 @@ EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
{ {
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
struct mwifiex_adapter *adapter = priv->adapter;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
mwifiex_dev_debugfs_remove(priv); mwifiex_dev_debugfs_remove(priv);
#endif #endif
mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); mwifiex_stop_net_dev_queue(priv->netdev, adapter);
if (netif_carrier_ok(priv->netdev)) if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev); netif_carrier_off(priv->netdev);
...@@ -2359,6 +2397,24 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) ...@@ -2359,6 +2397,24 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
priv->media_connected = false; priv->media_connected = false;
switch (priv->bss_mode) {
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
adapter->curr_iface_comb.sta_intf++;
break;
case NL80211_IFTYPE_AP:
adapter->curr_iface_comb.uap_intf++;
break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
adapter->curr_iface_comb.p2p_intf++;
break;
default:
dev_err(adapter->dev, "del_virtual_intf: type not supported\n");
break;
}
priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
......
...@@ -104,6 +104,10 @@ ...@@ -104,6 +104,10 @@
/* Rate index for OFDM 0 */ /* Rate index for OFDM 0 */
#define MWIFIEX_RATE_INDEX_OFDM0 4 #define MWIFIEX_RATE_INDEX_OFDM0 4
#define MWIFIEX_MAX_STA_NUM 1
#define MWIFIEX_MAX_UAP_NUM 1
#define MWIFIEX_MAX_P2P_NUM 1
enum mwifiex_bss_type { enum mwifiex_bss_type {
MWIFIEX_BSS_TYPE_STA = 0, MWIFIEX_BSS_TYPE_STA = 0,
MWIFIEX_BSS_TYPE_UAP = 1, MWIFIEX_BSS_TYPE_UAP = 1,
...@@ -232,4 +236,10 @@ struct mwifiex_histogram_data { ...@@ -232,4 +236,10 @@ struct mwifiex_histogram_data {
atomic_t num_samples; atomic_t num_samples;
}; };
struct mwifiex_iface_comb {
u8 sta_intf;
u8 uap_intf;
u8 p2p_intf;
};
#endif /* !_MWIFIEX_DECL_H_ */ #endif /* !_MWIFIEX_DECL_H_ */
...@@ -298,6 +298,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) ...@@ -298,6 +298,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->key_api_major_ver = 0; adapter->key_api_major_ver = 0;
adapter->key_api_minor_ver = 0; adapter->key_api_minor_ver = 0;
memset(adapter->perm_addr, 0xff, ETH_ALEN); memset(adapter->perm_addr, 0xff, ETH_ALEN);
adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM;
adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM;
adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
setup_timer(&adapter->wakeup_timer, wakeup_timer_fn, setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
(unsigned long)adapter); (unsigned long)adapter);
......
...@@ -730,6 +730,8 @@ struct mwifiex_if_ops { ...@@ -730,6 +730,8 @@ struct mwifiex_if_ops {
struct mwifiex_adapter { struct mwifiex_adapter {
u8 iface_type; u8 iface_type;
struct mwifiex_iface_comb iface_limit;
struct mwifiex_iface_comb curr_iface_comb;
struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM];
u8 priv_num; u8 priv_num;
const struct firmware *firmware; const struct firmware *firmware;
...@@ -1149,6 +1151,25 @@ mwifiex_get_priv(struct mwifiex_adapter *adapter, ...@@ -1149,6 +1151,25 @@ mwifiex_get_priv(struct mwifiex_adapter *adapter,
return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); return ((i < adapter->priv_num) ? adapter->priv[i] : NULL);
} }
/*
* This function returns the first available unused private structure pointer.
*/
static inline struct mwifiex_private *
mwifiex_get_unused_priv(struct mwifiex_adapter *adapter)
{
int i;
for (i = 0; i < adapter->priv_num; i++) {
if (adapter->priv[i]) {
if (adapter->priv[i]->bss_mode ==
NL80211_IFTYPE_UNSPECIFIED)
break;
}
}
return ((i < adapter->priv_num) ? adapter->priv[i] : NULL);
}
/* /*
* This function returns the driver private structure of a network device. * This function returns the driver private structure of a network device.
*/ */
......
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