From e48e0de0053f077dc8a98e1e06019024e93bb866 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 7 Feb 2014 16:30:33 -0800 Subject: [PATCH] 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 Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 18 ++++++++++++++++++ drivers/net/wireless/mwifiex/sta_cmd.c | 3 +++ drivers/net/wireless/mwifiex/sta_cmdresp.c | 15 +++++++++++++++ drivers/net/wireless/mwifiex/tdls.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+) 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; } -- 2.11.0