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

mwifiex: add cfg80211 add_station handler support

This patch adds cfg80211 add_station handler support for mwifiex
which is needed for TDLS setup. Driver issues create TDLS link
command to FW upon receiving add_station from cfg80211.
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 429d90d2
...@@ -2717,6 +2717,23 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, ...@@ -2717,6 +2717,23 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
return mwifiex_tdls_oper(priv, peer, action); return mwifiex_tdls_oper(priv, peer, action);
} }
static int
mwifiex_cfg80211_add_station(struct wiphy *wiphy,
struct net_device *dev,
u8 *mac, struct station_parameters *params)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
return -ENOTSUPP;
/* make sure we are in station mode and connected */
if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
return -ENOTSUPP;
return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);
}
/* station cfg80211 operations */ /* station cfg80211 operations */
static struct cfg80211_ops mwifiex_cfg80211_ops = { static struct cfg80211_ops mwifiex_cfg80211_ops = {
.add_virtual_intf = mwifiex_add_virtual_intf, .add_virtual_intf = mwifiex_add_virtual_intf,
...@@ -2754,6 +2771,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { ...@@ -2754,6 +2771,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
.set_coalesce = mwifiex_cfg80211_set_coalesce, .set_coalesce = mwifiex_cfg80211_set_coalesce,
.tdls_mgmt = mwifiex_cfg80211_tdls_mgmt, .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
.tdls_oper = mwifiex_cfg80211_tdls_oper, .tdls_oper = mwifiex_cfg80211_tdls_oper,
.add_station = mwifiex_cfg80211_add_station,
}; };
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -1300,6 +1300,9 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, ...@@ -1300,6 +1300,9 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
case MWIFIEX_TDLS_DISABLE_LINK: case MWIFIEX_TDLS_DISABLE_LINK:
tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE); tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE);
break; break;
case MWIFIEX_TDLS_CREATE_LINK:
tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE);
break;
default: default:
dev_err(priv->adapter->dev, "Unknown TDLS operation\n"); dev_err(priv->adapter->dev, "Unknown TDLS operation\n");
return -ENOTSUPP; return -ENOTSUPP;
......
...@@ -807,6 +807,8 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv, ...@@ -807,6 +807,8 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper; struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper;
u16 reason = le16_to_cpu(cmd_tdls_oper->reason); u16 reason = le16_to_cpu(cmd_tdls_oper->reason);
u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action); u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action);
struct mwifiex_sta_node *node =
mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac);
switch (action) { switch (action) {
case ACT_TDLS_DELETE: case ACT_TDLS_DELETE:
...@@ -819,6 +821,19 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv, ...@@ -819,6 +821,19 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
"TDLS link config for %pM successful\n", "TDLS link config for %pM successful\n",
cmd_tdls_oper->peer_mac); cmd_tdls_oper->peer_mac);
break; break;
case ACT_TDLS_CREATE:
if (reason) {
dev_err(priv->adapter->dev,
"TDLS link creation for %pM failed: reason %d",
cmd_tdls_oper->peer_mac, reason);
if (node && reason != TDLS_ERR_LINK_EXISTS)
node->tdls_status = TDLS_SETUP_FAILURE;
} else {
dev_dbg(priv->adapter->dev,
"TDLS link creation for %pM successful",
cmd_tdls_oper->peer_mac);
}
break;
default: default:
dev_err(priv->adapter->dev, dev_err(priv->adapter->dev,
"Unknown TDLS command action respnse %d", action); "Unknown TDLS command action respnse %d", action);
......
...@@ -543,6 +543,32 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, ...@@ -543,6 +543,32 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
return; return;
} }
static int
mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
{
struct mwifiex_sta_node *sta_ptr;
struct mwifiex_ds_tdls_oper tdls_oper;
memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
sta_ptr = mwifiex_get_sta_entry(priv, peer);
if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
dev_dbg(priv->adapter->dev,
"Setup already in progress for peer %pM\n", peer);
return 0;
}
sta_ptr = mwifiex_add_sta_entry(priv, peer);
if (!sta_ptr)
return -ENOMEM;
sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TDLS_OPER,
HostCmd_ACT_GEN_SET, 0, &tdls_oper);
}
static int static int
mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer) mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
{ {
...@@ -634,6 +660,8 @@ int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action) ...@@ -634,6 +660,8 @@ int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
return mwifiex_tdls_process_enable_link(priv, peer); return mwifiex_tdls_process_enable_link(priv, peer);
case MWIFIEX_TDLS_DISABLE_LINK: case MWIFIEX_TDLS_DISABLE_LINK:
return mwifiex_tdls_process_disable_link(priv, peer); return mwifiex_tdls_process_disable_link(priv, peer);
case MWIFIEX_TDLS_CREATE_LINK:
return mwifiex_tdls_process_create_link(priv, peer);
} }
return 0; return 0;
} }
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