Commit 9197ab9e authored by Stone Piao's avatar Stone Piao Committed by John W. Linville

mwifiex: add support for P2P GO in interface type change

When cfg80211 calls to change interface type for P2P GO, send
P2P mode config commands to firmware and set bss role and bss
mode accordingly.
Signed-off-by: default avatarStone Piao <piaoyun@marvell.com>
Signed-off-by: default avatarAvinash Patil <patila@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e1a2b7a3
...@@ -679,6 +679,9 @@ mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv) ...@@ -679,6 +679,9 @@ mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)
{ {
u16 mode = P2P_MODE_DISABLE; u16 mode = P2P_MODE_DISABLE;
if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA)
mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA);
if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG,
HostCmd_ACT_GEN_SET, 0, &mode)) HostCmd_ACT_GEN_SET, 0, &mode))
return -1; return -1;
...@@ -712,6 +715,35 @@ mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv) ...@@ -712,6 +715,35 @@ mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv)
return 0; return 0;
} }
/*
* This function initializes the functionalities for P2P GO.
* The P2P GO initialization sequence is:
* disable -> device -> GO
*/
static int
mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)
{
u16 mode;
if (mwifiex_cfg80211_deinit_p2p(priv))
return -1;
mode = P2P_MODE_DEVICE;
if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG,
HostCmd_ACT_GEN_SET, 0, &mode))
return -1;
mode = P2P_MODE_GO;
if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG,
HostCmd_ACT_GEN_SET, 0, &mode))
return -1;
if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_UAP);
return 0;
}
/* /*
* CFG802.11 operation handler to change interface type. * CFG802.11 operation handler to change interface type.
*/ */
...@@ -749,6 +781,11 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, ...@@ -749,6 +781,11 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
return -EFAULT; return -EFAULT;
dev->ieee80211_ptr->iftype = type; dev->ieee80211_ptr->iftype = type;
return 0; return 0;
case NL80211_IFTYPE_P2P_GO:
if (mwifiex_cfg80211_init_p2p_go(priv))
return -EFAULT;
dev->ieee80211_ptr->iftype = type;
return 0;
case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_UNSPECIFIED:
wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name);
case NL80211_IFTYPE_STATION: /* This shouldn't happen */ case NL80211_IFTYPE_STATION: /* This shouldn't happen */
...@@ -775,6 +812,7 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, ...@@ -775,6 +812,7 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
} }
break; break;
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
switch (type) { switch (type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
if (mwifiex_cfg80211_deinit_p2p(priv)) if (mwifiex_cfg80211_deinit_p2p(priv))
...@@ -1135,7 +1173,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, ...@@ -1135,7 +1173,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
{ {
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {
wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__); wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -1223,7 +1261,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, ...@@ -1223,7 +1261,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
u8 config_bands = 0; u8 config_bands = 0;
if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
return -1; return -1;
if (mwifiex_set_mgmt_ies(priv, &params->beacon)) if (mwifiex_set_mgmt_ies(priv, &params->beacon))
return -1; return -1;
......
...@@ -1379,6 +1379,7 @@ struct host_cmd_ds_802_11_ibss_status { ...@@ -1379,6 +1379,7 @@ struct host_cmd_ds_802_11_ibss_status {
#define CONNECTION_TYPE_INFRA 0 #define CONNECTION_TYPE_INFRA 0
#define CONNECTION_TYPE_ADHOC 1 #define CONNECTION_TYPE_ADHOC 1
#define CONNECTION_TYPE_AP 2
struct host_cmd_ds_set_bss_mode { struct host_cmd_ds_set_bss_mode {
u8 con_type; u8 con_type;
......
...@@ -144,7 +144,7 @@ static void scan_delay_timer_fn(unsigned long data) ...@@ -144,7 +144,7 @@ static void scan_delay_timer_fn(unsigned long data)
* Additionally, it also initializes all the locks and sets up all the * Additionally, it also initializes all the locks and sets up all the
* lists. * lists.
*/ */
static int mwifiex_init_priv(struct mwifiex_private *priv) int mwifiex_init_priv(struct mwifiex_private *priv)
{ {
u32 i; u32 i;
...@@ -648,6 +648,17 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) ...@@ -648,6 +648,17 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
} }
} }
/*
* This function frees the private structure, including cleans
* up the TX and RX queues and frees the BSS priority tables.
*/
void mwifiex_free_priv(struct mwifiex_private *priv)
{
mwifiex_clean_txrx(priv);
mwifiex_delete_bss_prio_tbl(priv);
mwifiex_free_curr_bcn(priv);
}
/* /*
* This function is used to shutdown the driver. * This function is used to shutdown the driver.
* *
......
...@@ -736,6 +736,9 @@ void mwifiex_stop_net_dev_queue(struct net_device *netdev, ...@@ -736,6 +736,9 @@ void mwifiex_stop_net_dev_queue(struct net_device *netdev,
void mwifiex_wake_up_net_dev_queue(struct net_device *netdev, void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
struct mwifiex_adapter *adapter); struct mwifiex_adapter *adapter);
int mwifiex_init_priv(struct mwifiex_private *priv);
void mwifiex_free_priv(struct mwifiex_private *priv);
int mwifiex_init_fw(struct mwifiex_adapter *adapter); int mwifiex_init_fw(struct mwifiex_adapter *adapter);
int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter);
...@@ -1018,6 +1021,8 @@ int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, ...@@ -1018,6 +1021,8 @@ int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
enum nl80211_channel_type *channel_type, enum nl80211_channel_type *channel_type,
unsigned int duration); unsigned int duration);
int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role);
int mwifiex_get_stats_info(struct mwifiex_private *priv, int mwifiex_get_stats_info(struct mwifiex_private *priv,
struct mwifiex_ds_get_stats *log); struct mwifiex_ds_get_stats *log);
......
...@@ -1261,6 +1261,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ...@@ -1261,6 +1261,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
else if (priv->bss_mode == NL80211_IFTYPE_STATION) else if (priv->bss_mode == NL80211_IFTYPE_STATION)
cmd_ptr->params.bss_mode.con_type = cmd_ptr->params.bss_mode.con_type =
CONNECTION_TYPE_INFRA; CONNECTION_TYPE_INFRA;
else if (priv->bss_mode == NL80211_IFTYPE_AP)
cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_AP;
cmd_ptr->size = cpu_to_le16(sizeof(struct cmd_ptr->size = cpu_to_le16(sizeof(struct
host_cmd_ds_set_bss_mode) + S_DS_GEN); host_cmd_ds_set_bss_mode) + S_DS_GEN);
ret = 0; ret = 0;
......
...@@ -1072,6 +1072,36 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, ...@@ -1072,6 +1072,36 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,
return roc_cfg.status; return roc_cfg.status;
} }
int
mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role)
{
if (GET_BSS_ROLE(priv) == bss_role) {
dev_dbg(priv->adapter->dev,
"info: already in the desired role.\n");
return 0;
}
mwifiex_free_priv(priv);
mwifiex_init_priv(priv);
priv->bss_role = bss_role;
switch (bss_role) {
case MWIFIEX_BSS_ROLE_UAP:
priv->bss_mode = NL80211_IFTYPE_AP;
break;
case MWIFIEX_BSS_ROLE_STA:
case MWIFIEX_BSS_ROLE_ANY:
default:
priv->bss_mode = NL80211_IFTYPE_STATION;
break;
}
mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE,
HostCmd_ACT_GEN_SET, 0, NULL);
return mwifiex_sta_init_cmd(priv, false);
}
/* /*
* Sends IOCTL request to get statistics information. * Sends IOCTL request to get statistics information.
* *
......
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