mwifiex: update domain_info upon band change in start_ap
[deliverable/linux.git] / drivers / net / wireless / mwifiex / cfg80211.c
index b15e4c7acbecd2ed44b1e76360464ef23f3fd9f3..1d445cbbb31b611bbaf7c8198b4d307274f2d464 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "cfg80211.h"
 #include "main.h"
+#include "11n.h"
 
 static char *reg_alpha2;
 module_param(reg_alpha2, charp, 0);
@@ -441,7 +442,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
  *      - Country codes
  *      - Sub bands (first channel, number of channels, maximum Tx power)
  */
-static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
+int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
 {
        u8 no_of_triplet = 0;
        struct ieee80211_country_ie_triplet *t;
@@ -3359,6 +3360,72 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
        return mwifiex_tdls_oper(priv, peer, action);
 }
 
+static int
+mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
+                                 const u8 *addr, u8 oper_class,
+                                 struct cfg80211_chan_def *chandef)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       unsigned long flags;
+       u16 chan;
+       u8 second_chan_offset, band;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       sta_ptr = mwifiex_get_sta_entry(priv, addr);
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+       if (!sta_ptr) {
+               wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
+                         __func__, addr);
+               return -ENOENT;
+       }
+
+       if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &
+             WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {
+               wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);
+               return -ENOENT;
+       }
+
+       if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
+           sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {
+               wiphy_err(wiphy, "channel switch is running, abort request\n");
+               return -EALREADY;
+       }
+
+       chan = chandef->chan->hw_value;
+       second_chan_offset = mwifiex_get_sec_chan_offset(chan);
+       band = chandef->chan->band;
+       mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band);
+
+       return 0;
+}
+
+static void
+mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,
+                                        struct net_device *dev,
+                                        const u8 *addr)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       unsigned long flags;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       sta_ptr = mwifiex_get_sta_entry(priv, addr);
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+       if (!sta_ptr) {
+               wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
+                         __func__, addr);
+       } else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
+                    sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||
+                    sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {
+               wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",
+                         addr);
+       } else
+               mwifiex_stop_tdls_cs(priv, addr);
+}
+
 static int
 mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
                             const u8 *mac, struct station_parameters *params)
@@ -3575,6 +3642,8 @@ 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,
+       .tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch,
+       .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch,
        .add_station = mwifiex_cfg80211_add_station,
        .change_station = mwifiex_cfg80211_change_station,
        .get_channel = mwifiex_cfg80211_get_channel,
@@ -3709,6 +3778,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
                           NL80211_FEATURE_INACTIVITY_TIMER |
                           NL80211_FEATURE_NEED_OBSS_SCAN;
 
+       if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
+               wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
+
        if (adapter->fw_api_ver == MWIFIEX_FW_V15)
                wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
 
This page took 0.029494 seconds and 5 git commands to generate.