This patch enables 11h extensions in FW upon detecting DFS
channel in start radar detection/channel switch handlers.
Patch also takes care of disabling 11h when non DFS channels
are to be set during start_ap handler.

Signed-off-by: Avinash Patil <[email protected]>
Signed-off-by: Qingshui Gao <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
 drivers/net/wireless/mwifiex/11h.c      | 18 +++++++++++++++++-
 drivers/net/wireless/mwifiex/cfg80211.c | 22 ++++++++++++++++++++++
 drivers/net/wireless/mwifiex/decl.h     |  5 +++++
 drivers/net/wireless/mwifiex/fw.h       |  2 ++
 drivers/net/wireless/mwifiex/init.c     |  2 ++
 drivers/net/wireless/mwifiex/main.h     |  5 +++++
 6 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mwifiex/11h.c 
b/drivers/net/wireless/mwifiex/11h.c
index d794686..3ab87a8 100644
--- a/drivers/net/wireless/mwifiex/11h.c
+++ b/drivers/net/wireless/mwifiex/11h.c
@@ -21,6 +21,16 @@
 #include "fw.h"
 
 
+void mwifiex_init_11h_params(struct mwifiex_private *priv)
+{
+       priv->state_11h.is_11h_enabled = true;
+       priv->state_11h.is_11h_active = false;
+}
+
+inline int mwifiex_is_11h_active(struct mwifiex_private *priv)
+{
+       return priv->state_11h.is_11h_active;
+}
 /* This function appends 11h info to a buffer while joining an
  * infrastructure BSS
  */
@@ -69,10 +79,14 @@ mwifiex_11h_process_infra_join(struct mwifiex_private 
*priv, u8 **buffer,
 }
 
 /* Enable or disable the 11h extensions in the firmware */
-static int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag)
+int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag)
 {
        u32 enable = flag;
 
+       /* enable master mode radar detection on AP interface */
+       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && enable)
+               enable |= MWIFIEX_MASTER_RADAR_DET_MASK;
+
        return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
                                HostCmd_ACT_GEN_SET, DOT11H_I, &enable, true);
 }
@@ -91,11 +105,13 @@ void mwifiex_11h_process_join(struct mwifiex_private 
*priv, u8 **buffer,
                 * bit
                 */
                mwifiex_11h_activate(priv, true);
+               priv->state_11h.is_11h_active = true;
                bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT;
                mwifiex_11h_process_infra_join(priv, buffer, bss_desc);
        } else {
                /* Deactivate 11h functions in the firmware */
                mwifiex_11h_activate(priv, false);
+               priv->state_11h.is_11h_active = false;
                bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT;
        }
 }
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c 
b/drivers/net/wireless/mwifiex/cfg80211.c
index 2d1ea93..41c8e25 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1742,6 +1742,18 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 
        mwifiex_set_wmm_params(priv, bss_cfg, params);
 
+       if (mwifiex_is_11h_active(priv) &&
+           !cfg80211_chandef_dfs_required(wiphy, &params->chandef,
+                                          priv->bss_mode)) {
+               dev_dbg(priv->adapter->dev, "Disable 11h extensions in FW\n");
+               if (mwifiex_11h_activate(priv, false)) {
+                       dev_err(priv->adapter->dev,
+                               "Failed to disable 11h extensions!!");
+                       return -1;
+               }
+               priv->state_11h.is_11h_active = true;
+       }
+
        if (mwifiex_config_start_uap(priv, bss_cfg)) {
                wiphy_err(wiphy, "Failed to start AP\n");
                kfree(bss_cfg);
@@ -3209,6 +3221,16 @@ mwifiex_cfg80211_start_radar_detection(struct wiphy 
*wiphy,
                return -EBUSY;
        }
 
+       if (!mwifiex_is_11h_active(priv)) {
+               dev_dbg(priv->adapter->dev, "Enable 11h extensions in FW\n");
+               if (mwifiex_11h_activate(priv, true)) {
+                       dev_err(priv->adapter->dev,
+                               "Failed to activate 11h extensions!!");
+                       return -1;
+               }
+               priv->state_11h.is_11h_active = true;
+       }
+
        memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
        radar_params.chandef = chandef;
        radar_params.cac_time_ms = cac_time_ms;
diff --git a/drivers/net/wireless/mwifiex/decl.h 
b/drivers/net/wireless/mwifiex/decl.h
index 68aed4e..88d0ead 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -248,4 +248,9 @@ struct mwifiex_radar_params {
        struct cfg80211_chan_def *chandef;
        u32 cac_time_ms;
 } __packed;
+
+struct mwifiex_11h_intf_state {
+       bool is_11h_enabled;
+       bool is_11h_active;
+} __packed;
 #endif /* !_MWIFIEX_DECL_H_ */
diff --git a/drivers/net/wireless/mwifiex/fw.h 
b/drivers/net/wireless/mwifiex/fw.h
index 6d433227..df553e8 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -534,6 +534,8 @@ enum P2P_MODES {
 
 #define MWIFIEX_FW_V15            15
 
+#define MWIFIEX_MASTER_RADAR_DET_MASK BIT(1)
+
 struct mwifiex_ie_types_header {
        __le16 type;
        __le16 len;
diff --git a/drivers/net/wireless/mwifiex/init.c 
b/drivers/net/wireless/mwifiex/init.c
index aa239a8..b77ba74 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -152,6 +152,8 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
        priv->check_tdls_tx = false;
        memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID);
 
+       mwifiex_init_11h_params(priv);
+
        return mwifiex_add_bss_prio_tbl(priv);
 }
 
diff --git a/drivers/net/wireless/mwifiex/main.h 
b/drivers/net/wireless/mwifiex/main.h
index 599698c..f0a6af1 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -595,6 +595,7 @@ struct mwifiex_private {
        struct workqueue_struct *dfs_chan_sw_workqueue;
        struct delayed_work dfs_chan_sw_work;
        struct cfg80211_beacon_data beacon_after;
+       struct mwifiex_11h_intf_state state_11h;
 };
 
 enum mwifiex_ba_status {
@@ -1337,6 +1338,10 @@ int mwifiex_config_start_uap(struct mwifiex_private 
*priv,
 void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
                              struct mwifiex_sta_node *node);
 
+void mwifiex_init_11h_params(struct mwifiex_private *priv);
+int mwifiex_is_11h_active(struct mwifiex_private *priv);
+int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag);
+
 void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer,
                              struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv);
-- 
1.8.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to