summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2014-02-07 16:30:33 -0800
committerJohn W. Linville <linville@tuxdriver.com>2014-02-12 15:36:20 -0500
commite48e0de0053f077dc8a98e1e06019024e93bb866 (patch)
tree10eedf866f8977b0a94630d0182d0588cd67d6cf /drivers/net
parent429d90d2212b561859767a74e3bb855f32b4600d (diff)
downloadlinux-e48e0de0053f077dc8a98e1e06019024e93bb866.tar.bz2
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: Avinash Patil <patila@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c18
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c3
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c15
-rw-r--r--drivers/net/wireless/mwifiex/tdls.c28
4 files changed, 64 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 88cff9ca5577..cac8aea69ce5 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2717,6 +2717,23 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
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 */
static struct cfg80211_ops mwifiex_cfg80211_ops = {
.add_virtual_intf = mwifiex_add_virtual_intf,
@@ -2754,6 +2771,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
.set_coalesce = mwifiex_cfg80211_set_coalesce,
.tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
.tdls_oper = mwifiex_cfg80211_tdls_oper,
+ .add_station = mwifiex_cfg80211_add_station,
};
#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 4559f84e64b5..1e36fa7a6463 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1300,6 +1300,9 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
case MWIFIEX_TDLS_DISABLE_LINK:
tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE);
break;
+ case MWIFIEX_TDLS_CREATE_LINK:
+ tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE);
+ break;
default:
dev_err(priv->adapter->dev, "Unknown TDLS operation\n");
return -ENOTSUPP;
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index cb17f490bc6d..396b93682bd8 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -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;
u16 reason = le16_to_cpu(cmd_tdls_oper->reason);
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) {
case ACT_TDLS_DELETE:
@@ -819,6 +821,19 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
"TDLS link config for %pM successful\n",
cmd_tdls_oper->peer_mac);
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:
dev_err(priv->adapter->dev,
"Unknown TDLS command action respnse %d", action);
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index 7fead7bf768f..1d5ed70432d6 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -544,6 +544,32 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
}
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
mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
{
struct mwifiex_sta_node *sta_ptr;
@@ -634,6 +660,8 @@ int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
return mwifiex_tdls_process_enable_link(priv, peer);
case MWIFIEX_TDLS_DISABLE_LINK:
return mwifiex_tdls_process_disable_link(priv, peer);
+ case MWIFIEX_TDLS_CREATE_LINK:
+ return mwifiex_tdls_process_create_link(priv, peer);
}
return 0;
}