linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP
@ 2015-01-28 10:24 Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 01/10] mwifiex: do not send regulatory update while starting AP Avinash Patil
                   ` (9 more replies)
  0 siblings, 10 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

This patch series adds DFS support for mwifiex AP. Series include
patches to handle cfg80211 start_radar_detection and channel_switch
handlers. First 5 patches are actually refactoring effort. Patch6-10
add these handlers and other DFS handling.

Avinash Patil (10):
  mwifiex: do not send regulatory update while starting AP
  mwifiex: store AP configuration in private structure
  mwifiex: update IEs after AP has started
  mwifiex: refactor start_ap handler
  mwifiex: separate function for parsing head and tail IEs
  mwifiex: add cfg80211 start_radar_detection handler
  mwifiex: support for channel report for radar detection
  mwifiex: handle radar detect event from FW
  mwifiex: channel switch support for mwifiex
  mwifiex: 11h handling for AP interface

 drivers/net/wireless/mwifiex/11h.c         | 196 +++++++++++++++++++++++-
 drivers/net/wireless/mwifiex/cfg80211.c    | 232 +++++++++++++++++++++--------
 drivers/net/wireless/mwifiex/decl.h        |  11 ++
 drivers/net/wireless/mwifiex/fw.h          |  58 ++++++++
 drivers/net/wireless/mwifiex/ie.c          |  89 ++++++-----
 drivers/net/wireless/mwifiex/init.c        |   3 +
 drivers/net/wireless/mwifiex/main.c        |   2 +-
 drivers/net/wireless/mwifiex/main.h        |  31 +++-
 drivers/net/wireless/mwifiex/sta_cmd.c     |   4 +
 drivers/net/wireless/mwifiex/sta_cmdresp.c |   2 +
 drivers/net/wireless/mwifiex/sta_event.c   |  10 ++
 drivers/net/wireless/mwifiex/uap_cmd.c     |  70 +++++++++
 drivers/net/wireless/mwifiex/uap_event.c   |   8 +
 13 files changed, 619 insertions(+), 97 deletions(-)

-- 
1.8.1.4


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 01/10] mwifiex: do not send regulatory update while starting AP
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  2015-01-29  8:26   ` [v2, " Kalle Valo
  2015-01-28 10:24 ` [PATCH v2 02/10] mwifiex: store AP configuration in private structure Avinash Patil
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

When regulatory domain changes, cfg80211 already issues request
to change regulatory domain to driver via reg_notifier.
There is no need to set regulatory again during start_ap.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/cfg80211.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 30ea94a..1acccc5 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1739,7 +1739,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 		priv->adapter->config_bands = config_bands;
 
 	mwifiex_set_uap_rates(bss_cfg, params);
-	mwifiex_send_domain_info_cmd_fw(wiphy);
 
 	if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
 		kfree(bss_cfg);
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 02/10] mwifiex: store AP configuration in private structure
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 01/10] mwifiex: do not send regulatory update while starting AP Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 03/10] mwifiex: update IEs after AP has started Avinash Patil
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

Store AP configuration in private structure so that we know
current AP configuration.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/cfg80211.c | 2 ++
 drivers/net/wireless/mwifiex/main.h     | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 1acccc5..8e07564 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1655,6 +1655,7 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 		wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
 
 	priv->ap_11n_enabled = 0;
+	memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg));
 
 	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
 			     HostCmd_ACT_GEN_SET, 0, NULL, true)) {
@@ -1782,6 +1783,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 		return -1;
 	}
 
+	memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
 	kfree(bss_cfg);
 
 	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 9e839cd..673252a 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -577,6 +577,7 @@ struct mwifiex_private {
 	unsigned long csa_expire_time;
 	u8 del_list_idx;
 	bool hs2_enabled;
+	struct mwifiex_uap_bss_param bss_cfg;
 	struct station_parameters *sta_params;
 	struct sk_buff_head tdls_txq;
 	u8 check_tdls_tx;
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 03/10] mwifiex: update IEs after AP has started
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 01/10] mwifiex: do not send regulatory update while starting AP Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 02/10] mwifiex: store AP configuration in private structure Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 04/10] mwifiex: refactor start_ap handler Avinash Patil
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

This patch moves IE management routine to end of start_ap handler.
IEs now would be updated after AP has started.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/cfg80211.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 8e07564..ceeaeac 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1681,8 +1681,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 
 	if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
 		return -1;
-	if (mwifiex_set_mgmt_ies(priv, &params->beacon))
-		return -1;
 
 	bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
 	if (!bss_cfg)
@@ -1783,6 +1781,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 		return -1;
 	}
 
+	if (mwifiex_set_mgmt_ies(priv, &params->beacon))
+		return -1;
+
 	memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
 	kfree(bss_cfg);
 
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 04/10] mwifiex: refactor start_ap handler
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
                   ` (2 preceding siblings ...)
  2015-01-28 10:24 ` [PATCH v2 03/10] mwifiex: update IEs after AP has started Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 05/10] mwifiex: separate function for parsing head and tail IEs Avinash Patil
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

Refactor mwifiex_cfg80211_start_ap by creating separate function
to set AP channel and another for configuring other AP parameters
and starting AP.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/cfg80211.c | 68 ++++-----------------------------
 drivers/net/wireless/mwifiex/main.h     |  4 ++
 drivers/net/wireless/mwifiex/uap_cmd.c  | 65 +++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+), 60 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index ceeaeac..2e0834c 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1677,7 +1677,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 {
 	struct mwifiex_uap_bss_param *bss_cfg;
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-	u8 config_bands = 0;
 
 	if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
 		return -1;
@@ -1697,6 +1696,11 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 		memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);
 		bss_cfg->ssid.ssid_len = params->ssid_len;
 	}
+	if (params->inactivity_timeout > 0) {
+		/* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */
+		bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout;
+		bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout;
+	}
 
 	switch (params->hidden_ssid) {
 	case NL80211_HIDDEN_SSID_NOT_IN_USE:
@@ -1712,31 +1716,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 		return -EINVAL;
 	}
 
-	bss_cfg->channel = ieee80211_frequency_to_channel(
-				params->chandef.chan->center_freq);
-
-	/* Set appropriate bands */
-	if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
-		bss_cfg->band_cfg = BAND_CONFIG_BG;
-		config_bands = BAND_B | BAND_G;
-
-		if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
-			config_bands |= BAND_GN;
-	} else {
-		bss_cfg->band_cfg = BAND_CONFIG_A;
-		config_bands = BAND_A;
-
-		if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
-			config_bands |= BAND_AN;
-
-		if (params->chandef.width > NL80211_CHAN_WIDTH_40)
-			config_bands |= BAND_AAC;
-	}
-
-	if (!((config_bands | priv->adapter->fw_bands) &
-	      ~priv->adapter->fw_bands))
-		priv->adapter->config_bands = config_bands;
-
+	mwifiex_uap_set_channel(bss_cfg, params->chandef);
 	mwifiex_set_uap_rates(bss_cfg, params);
 
 	if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
@@ -1760,23 +1740,8 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 
 	mwifiex_set_wmm_params(priv, bss_cfg, params);
 
-	if (params->inactivity_timeout > 0) {
-		/* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */
-		bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout;
-		bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout;
-	}
-
-	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
-			     HostCmd_ACT_GEN_SET, 0, NULL, true)) {
-		wiphy_err(wiphy, "Failed to stop the BSS\n");
-		kfree(bss_cfg);
-		return -1;
-	}
-
-	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
-			     HostCmd_ACT_GEN_SET,
-			     UAP_BSS_PARAMS_I, bss_cfg, false)) {
-		wiphy_err(wiphy, "Failed to set the SSID\n");
+	if (mwifiex_config_start_uap(priv, bss_cfg)) {
+		wiphy_err(wiphy, "Failed to start AP\n");
 		kfree(bss_cfg);
 		return -1;
 	}
@@ -1786,23 +1751,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 
 	memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
 	kfree(bss_cfg);
-
-	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
-			     HostCmd_ACT_GEN_SET, 0, NULL, false)) {
-		wiphy_err(wiphy, "Failed to start the BSS\n");
-		return -1;
-	}
-
-	if (priv->sec_info.wep_enabled)
-		priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
-	else
-		priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
-
-	if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
-			     HostCmd_ACT_GEN_SET, 0,
-			     &priv->curr_pkt_filter, true))
-		return -1;
-
 	return 0;
 }
 
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 673252a..0c75eff 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -1321,6 +1321,10 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
 			 struct cfg80211_beacon_data *data);
 int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
 u8 *mwifiex_11d_code_2_region(u8 code);
+void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg,
+			     struct cfg80211_chan_def chandef);
+int mwifiex_config_start_uap(struct mwifiex_private *priv,
+			     struct mwifiex_uap_bss_param *bss_cfg);
 void mwifiex_uap_del_sta_data(struct mwifiex_private *priv,
 			      struct mwifiex_sta_node *node);
 
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index 0f347fd..baf5314 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -769,3 +769,68 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
 
 	return 0;
 }
+
+void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg,
+			     struct cfg80211_chan_def chandef)
+{
+	u8 config_bands = 0;
+
+	bss_cfg->channel = ieee80211_frequency_to_channel(
+						     chandef.chan->center_freq);
+
+	/* Set appropriate bands */
+	if (chandef.chan->band == IEEE80211_BAND_2GHZ) {
+		bss_cfg->band_cfg = BAND_CONFIG_BG;
+		config_bands = BAND_B | BAND_G;
+
+		if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
+			config_bands |= BAND_GN;
+	} else {
+		bss_cfg->band_cfg = BAND_CONFIG_A;
+		config_bands = BAND_A;
+
+		if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
+			config_bands |= BAND_AN;
+
+		if (chandef.width > NL80211_CHAN_WIDTH_40)
+			config_bands |= BAND_AAC;
+	}
+}
+
+int mwifiex_config_start_uap(struct mwifiex_private *priv,
+			     struct mwifiex_uap_bss_param *bss_cfg)
+{
+	if (mwifiex_del_mgmt_ies(priv))
+		dev_err(priv->adapter->dev, "Failed to delete mgmt IEs!\n");
+
+	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
+			     HostCmd_ACT_GEN_SET, 0, NULL, true)) {
+		dev_err(priv->adapter->dev, "Failed to stop the BSS\n");
+		return -1;
+	}
+
+	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
+			     HostCmd_ACT_GEN_SET,
+			     UAP_BSS_PARAMS_I, bss_cfg, false)) {
+		dev_err(priv->adapter->dev, "Failed to set the SSID\n");
+		return -1;
+	}
+
+	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
+			     HostCmd_ACT_GEN_SET, 0, NULL, false)) {
+		dev_err(priv->adapter->dev, "Failed to start the BSS\n");
+		return -1;
+	}
+
+	if (priv->sec_info.wep_enabled)
+		priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
+	else
+		priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
+
+	if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL,
+			     HostCmd_ACT_GEN_SET, 0,
+			     &priv->curr_pkt_filter, true))
+		return -1;
+
+	return 0;
+}
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 05/10] mwifiex: separate function for parsing head and tail IEs
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
                   ` (3 preceding siblings ...)
  2015-01-28 10:24 ` [PATCH v2 04/10] mwifiex: refactor start_ap handler Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 06/10] mwifiex: add cfg80211 start_radar_detection handler Avinash Patil
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

Head & Tail IEs are supposed to be added to beacon and probe response.
This patch adds separate function for parsing head and tail IEs from
cfg80211_beacon_data and sets them to FW.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/ie.c   | 81 +++++++++++++++++++++----------------
 drivers/net/wireless/mwifiex/main.c |  2 +-
 drivers/net/wireless/mwifiex/main.h |  2 +-
 3 files changed, 48 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c
index b933794..a6af7b8 100644
--- a/drivers/net/wireless/mwifiex/ie.c
+++ b/drivers/net/wireless/mwifiex/ie.c
@@ -317,27 +317,26 @@ done:
 	return ret;
 }
 
-/* This function parses different IEs-tail IEs, beacon IEs, probe response IEs,
- * association response IEs from cfg80211_ap_settings function and sets these IE
- * to FW.
+/* This function parses  head and tail IEs, from cfg80211_beacon_data and sets
+ * these IE to FW.
  */
-int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
-			 struct cfg80211_beacon_data *info)
+static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv,
+					 struct cfg80211_beacon_data *info)
 {
 	struct mwifiex_ie *gen_ie;
-	struct ieee_types_header *rsn_ie, *wpa_ie = NULL;
-	u16 rsn_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
+	struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL;
+	u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
 	const u8 *vendor_ie;
 
-	if (info->tail && info->tail_len) {
-		gen_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
-		if (!gen_ie)
-			return -ENOMEM;
-		gen_ie->ie_index = cpu_to_le16(rsn_idx);
-		gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
-							MGMT_MASK_PROBE_RESP |
-							MGMT_MASK_ASSOC_RESP);
+	gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL);
+	if (!gen_ie)
+		return -ENOMEM;
+	gen_ie->ie_index = cpu_to_le16(gen_idx);
+	gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
+						MGMT_MASK_PROBE_RESP |
+						MGMT_MASK_ASSOC_RESP);
 
+	if (info->tail && info->tail_len) {
 		rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN,
 						  info->tail, info->tail_len);
 		if (rsn_ie) {
@@ -357,20 +356,33 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
 			ie_len += wpa_ie->len + 2;
 			gen_ie->ie_length = cpu_to_le16(ie_len);
 		}
+	}
 
-		if (rsn_ie || wpa_ie) {
-			if (mwifiex_update_uap_custom_ie(priv, gen_ie, &rsn_idx,
-							 NULL, NULL,
-							 NULL, NULL)) {
-				kfree(gen_ie);
-				return -1;
-			}
-			priv->rsn_idx = rsn_idx;
+	if (rsn_ie || wpa_ie) {
+		if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL,
+						 NULL, NULL, NULL)) {
+			kfree(gen_ie);
+			return -1;
 		}
-
-		kfree(gen_ie);
+		priv->gen_idx = gen_idx;
 	}
 
+	kfree(gen_ie);
+	return 0;
+}
+
+/* This function parses different IEs-head & tail IEs, beacon IEs,
+ * probe response IEs, association response IEs from cfg80211_ap_settings
+ * function and sets these IE to FW.
+ */
+int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
+			 struct cfg80211_beacon_data *info)
+{
+	int ret;
+
+	ret = mwifiex_uap_set_head_tail_ies(priv, info);
+		return ret;
+
 	return mwifiex_set_mgmt_beacon_data_ies(priv, info);
 }
 
@@ -378,25 +390,25 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
 int mwifiex_del_mgmt_ies(struct mwifiex_private *priv)
 {
 	struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL;
-	struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL;
+	struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL;
 	int ret = 0;
 
-	if (priv->rsn_idx != MWIFIEX_AUTO_IDX_MASK) {
-		rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
-		if (!rsn_ie)
+	if (priv->gen_idx != MWIFIEX_AUTO_IDX_MASK) {
+		gen_ie = kmalloc(sizeof(*gen_ie), GFP_KERNEL);
+		if (!gen_ie)
 			return -ENOMEM;
 
-		rsn_ie->ie_index = cpu_to_le16(priv->rsn_idx);
-		rsn_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
-		rsn_ie->ie_length = 0;
-		if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &priv->rsn_idx,
+		gen_ie->ie_index = cpu_to_le16(priv->gen_idx);
+		gen_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK);
+		gen_ie->ie_length = 0;
+		if (mwifiex_update_uap_custom_ie(priv, gen_ie, &priv->gen_idx,
 						 NULL, &priv->proberesp_idx,
 						 NULL, &priv->assocresp_idx)) {
 			ret = -1;
 			goto done;
 		}
 
-		priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK;
+		priv->gen_idx = MWIFIEX_AUTO_IDX_MASK;
 	}
 
 	if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) {
@@ -440,7 +452,6 @@ done:
 	kfree(beacon_ie);
 	kfree(pr_ie);
 	kfree(ar_ie);
-	kfree(rsn_ie);
 
 	return ret;
 }
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 30e5193..7e74b4f 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -973,7 +973,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
 	priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK;
 	priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK;
 	priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK;
-	priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK;
+	priv->gen_idx = MWIFIEX_AUTO_IDX_MASK;
 	priv->num_tx_timeout = 0;
 	ether_addr_copy(priv->curr_addr, priv->adapter->perm_addr);
 	memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 0c75eff..c5ac20d 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -567,7 +567,7 @@ struct mwifiex_private {
 	u16 beacon_idx;
 	u16 proberesp_idx;
 	u16 assocresp_idx;
-	u16 rsn_idx;
+	u16 gen_idx;
 	u8 ap_11n_enabled;
 	u8 ap_11ac_enabled;
 	u32 mgmt_frame_mask;
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 06/10] mwifiex: add cfg80211 start_radar_detection handler
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
                   ` (4 preceding siblings ...)
  2015-01-28 10:24 ` [PATCH v2 05/10] mwifiex: separate function for parsing head and tail IEs Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 07/10] mwifiex: support for channel report for radar detection Avinash Patil
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

This patch adds support for cfg80211 start_radar_detection handler.
Upon reception of start_radar_detection, driver prepares radar detect
command to FW.

Delayed work is queued for CAC time which sends radar detection finished
event to cfg80211.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/11h.c         | 66 ++++++++++++++++++++++++++++++
 drivers/net/wireless/mwifiex/cfg80211.c    | 59 ++++++++++++++++++++++++++
 drivers/net/wireless/mwifiex/decl.h        |  6 +++
 drivers/net/wireless/mwifiex/fw.h          | 13 ++++++
 drivers/net/wireless/mwifiex/init.c        |  1 +
 drivers/net/wireless/mwifiex/main.h        | 10 +++++
 drivers/net/wireless/mwifiex/sta_cmd.c     |  4 ++
 drivers/net/wireless/mwifiex/sta_cmdresp.c |  2 +
 drivers/net/wireless/mwifiex/uap_cmd.c     |  5 +++
 9 files changed, 166 insertions(+)

diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c
index f23b647a..8832c83 100644
--- a/drivers/net/wireless/mwifiex/11h.c
+++ b/drivers/net/wireless/mwifiex/11h.c
@@ -99,3 +99,69 @@ void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer,
 		bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT;
 	}
 }
+
+/* This is DFS CAC work queue function.
+ * This delayed work emits CAC finished event for cfg80211 if
+ * CAC was started earlier.
+ */
+void mwifiex_dfs_cac_work_queue(struct work_struct *work)
+{
+	struct cfg80211_chan_def chandef;
+	struct delayed_work *delayed_work =
+			container_of(work, struct delayed_work, work);
+	struct mwifiex_private *priv =
+			container_of(delayed_work, struct mwifiex_private,
+				     dfs_cac_work);
+
+	if (WARN_ON(!priv))
+		return;
+
+	chandef = priv->dfs_chandef;
+	if (priv->wdev.cac_started) {
+		dev_dbg(priv->adapter->dev,
+			"CAC timer finished; No radar detected\n");
+		cfg80211_cac_event(priv->netdev, &chandef,
+				   NL80211_RADAR_CAC_FINISHED,
+				   GFP_KERNEL);
+	}
+}
+
+/* This function prepares channel report request command to FW for
+ * starting radar detection.
+ */
+int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
+					  struct host_cmd_ds_command *cmd,
+					  void *data_buf)
+{
+	struct host_cmd_ds_chan_rpt_req *cr_req = &cmd->params.chan_rpt_req;
+	struct mwifiex_radar_params *radar_params = (void *)data_buf;
+
+	cmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST);
+	cmd->size = cpu_to_le16(S_DS_GEN);
+	le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_chan_rpt_req));
+
+	cr_req->chan_desc.start_freq = cpu_to_le16(MWIFIEX_A_BAND_START_FREQ);
+	cr_req->chan_desc.chan_num = radar_params->chandef->chan->hw_value;
+	cr_req->chan_desc.chan_width = radar_params->chandef->width;
+	cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms);
+
+	dev_dbg(priv->adapter->dev,
+		"11h: issuing DFS Radar check for channel=%d\n",
+		radar_params->chandef->chan->hw_value);
+
+	return 0;
+}
+
+/* This function is to abort ongoing CAC upon stopping AP operations
+ * or during unload.
+ */
+void mwifiex_abort_cac(struct mwifiex_private *priv)
+{
+	if (priv->wdev.cac_started) {
+		dev_dbg(priv->adapter->dev,
+			"Aborting delayed work for CAC.\n");
+		cancel_delayed_work_sync(&priv->dfs_cac_work);
+		cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
+				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+	}
+}
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 2e0834c..7a969fd 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1651,6 +1651,8 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 {
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
+	mwifiex_abort_cac(priv);
+
 	if (mwifiex_del_mgmt_ies(priv))
 		wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
 
@@ -2383,6 +2385,7 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
 	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 }
 
+#define MWIFIEX_MAX_WQ_LEN  30
 /*
  *  create a new virtual interface with the given name
  */
@@ -2396,6 +2399,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 	struct mwifiex_private *priv;
 	struct net_device *dev;
 	void *mdev_priv;
+	char dfs_cac_str[MWIFIEX_MAX_WQ_LEN];
 
 	if (!adapter)
 		return ERR_PTR(-EFAULT);
@@ -2560,6 +2564,24 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 		return ERR_PTR(-EFAULT);
 	}
 
+	strcpy(dfs_cac_str, "MWIFIEX_DFS_CAC");
+	strcat(dfs_cac_str, name);
+	priv->dfs_cac_workqueue = alloc_workqueue(dfs_cac_str,
+						  WQ_HIGHPRI |
+						  WQ_MEM_RECLAIM |
+						  WQ_UNBOUND, 1);
+	if (!priv->dfs_cac_workqueue) {
+		wiphy_err(wiphy, "cannot register virtual network device\n");
+		free_netdev(dev);
+		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+		priv->netdev = NULL;
+		memset(&priv->wdev, 0, sizeof(priv->wdev));
+		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+		return ERR_PTR(-ENOMEM);
+	}
+
+	INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
+
 	sema_init(&priv->async_sem, 1);
 
 	dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
@@ -2609,6 +2631,12 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 	if (wdev->netdev->reg_state == NETREG_REGISTERED)
 		unregister_netdevice(wdev->netdev);
 
+	if (priv->dfs_cac_workqueue) {
+		flush_workqueue(priv->dfs_cac_workqueue);
+		destroy_workqueue(priv->dfs_cac_workqueue);
+		priv->dfs_cac_workqueue = NULL;
+	}
+
 	/* Clear the priv in adapter */
 	priv->netdev->ieee80211_ptr = NULL;
 	priv->netdev = NULL;
@@ -3088,6 +3116,36 @@ mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int
+mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
+				       struct net_device *dev,
+				       struct cfg80211_chan_def *chandef,
+				       u32 cac_time_ms)
+{
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+	struct mwifiex_radar_params radar_params;
+
+	if (priv->adapter->scan_processing) {
+		dev_err(priv->adapter->dev,
+			"radar detection: scan already in process...\n");
+		return -EBUSY;
+	}
+
+	memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
+	radar_params.chandef = chandef;
+	radar_params.cac_time_ms = cac_time_ms;
+
+	memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef));
+
+	if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+			     HostCmd_ACT_GEN_SET, 0, &radar_params, true))
+		return -1;
+
+	queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work,
+			   msecs_to_jiffies(cac_time_ms));
+	return 0;
+}
+
+static int
 mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
 				const u8 *mac,
 				struct station_parameters *params)
@@ -3151,6 +3209,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
 	.tdls_oper = mwifiex_cfg80211_tdls_oper,
 	.add_station = mwifiex_cfg80211_add_station,
 	.change_station = mwifiex_cfg80211_change_station,
+	.start_radar_detection = mwifiex_cfg80211_start_radar_detection,
 };
 
 #ifdef CONFIG_PM
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 4481ac4..68aed4e 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -108,6 +108,8 @@
 #define MWIFIEX_MAX_UAP_NUM		1
 #define MWIFIEX_MAX_P2P_NUM		1
 
+#define MWIFIEX_A_BAND_START_FREQ	5000
+
 enum mwifiex_bss_type {
 	MWIFIEX_BSS_TYPE_STA = 0,
 	MWIFIEX_BSS_TYPE_UAP = 1,
@@ -242,4 +244,8 @@ struct mwifiex_iface_comb {
 	u8 p2p_intf;
 };
 
+struct mwifiex_radar_params {
+	struct cfg80211_chan_def *chandef;
+	u32 cac_time_ms;
+} __packed;
 #endif /* !_MWIFIEX_DECL_H_ */
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 15ad776..739151c 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -336,6 +336,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_11N_ADDBA_RSP                     0x00cf
 #define HostCmd_CMD_11N_DELBA                         0x00d0
 #define HostCmd_CMD_RECONFIGURE_TX_BUFF               0x00d9
+#define HostCmd_CMD_CHAN_REPORT_REQUEST               0x00dd
 #define HostCmd_CMD_AMSDU_AGGR_CTRL                   0x00df
 #define HostCmd_CMD_TXPWR_CFG                         0x00d1
 #define HostCmd_CMD_TX_RATE_CFG                       0x00d6
@@ -1216,6 +1217,17 @@ struct host_cmd_ds_tdls_oper {
 	u8 peer_mac[ETH_ALEN];
 } __packed;
 
+struct mwifiex_chan_desc {
+	__le16 start_freq;
+	u8 chan_width;
+	u8 chan_num;
+} __packed;
+
+struct host_cmd_ds_chan_rpt_req {
+	struct mwifiex_chan_desc chan_desc;
+	__le32 msec_dwell_time;
+} __packed;
+
 struct mwifiex_fixed_bcn_param {
 	__le64 timestamp;
 	__le16 beacon_period;
@@ -1904,6 +1916,7 @@ struct host_cmd_ds_command {
 		struct host_cmd_11ac_vht_cfg vht_cfg;
 		struct host_cmd_ds_coalesce_cfg coalesce_cfg;
 		struct host_cmd_ds_tdls_oper tdls_oper;
+		struct host_cmd_ds_chan_rpt_req chan_rpt_req;
 	} params;
 } __packed;
 
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 1d1c3c8..aa239a8 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -681,6 +681,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
 			priv = adapter->priv[i];
 
 			mwifiex_clean_auto_tdls(priv);
+			mwifiex_abort_cac(priv);
 			mwifiex_clean_txrx(priv);
 			mwifiex_delete_bss_prio_tbl(priv);
 		}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index c5ac20d..e266d99 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -588,6 +588,9 @@ struct mwifiex_private {
 	spinlock_t ack_status_lock;
 	/** rx histogram data */
 	struct mwifiex_histogram_data *hist_data;
+	struct cfg80211_chan_def dfs_chandef;
+	struct workqueue_struct *dfs_cac_workqueue;
+	struct delayed_work dfs_cac_work;
 };
 
 enum mwifiex_ba_status {
@@ -754,6 +757,8 @@ struct mwifiex_adapter {
 	struct work_struct main_work;
 	struct workqueue_struct *rx_workqueue;
 	struct work_struct rx_work;
+	struct workqueue_struct *dfs_workqueue;
+	struct work_struct dfs_work;
 	bool rx_work_enabled;
 	bool rx_processing;
 	bool delay_main_work;
@@ -1376,6 +1381,9 @@ void mwifiex_check_auto_tdls(unsigned long context);
 void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac);
 void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv);
 void mwifiex_clean_auto_tdls(struct mwifiex_private *priv);
+int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
+					  struct host_cmd_ds_command *cmd,
+					  void *data_buf);
 
 void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
 				   void *event_body);
@@ -1383,6 +1391,8 @@ void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
 struct sk_buff *
 mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
 				struct sk_buff *skb, u8 flag, u64 *cookie);
+void mwifiex_dfs_cac_work_queue(struct work_struct *work);
+void mwifiex_abort_cac(struct mwifiex_private *priv);
 
 void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr,
 			   s8 nflr);
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 92a66e8..f7d204f 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1897,6 +1897,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
 	case HostCmd_CMD_TDLS_OPER:
 		ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf);
 		break;
+	case HostCmd_CMD_CHAN_REPORT_REQUEST:
+		ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr,
+							    data_buf);
+		break;
 	default:
 		dev_err(priv->adapter->dev,
 			"PREP_CMD: unknown cmd- %#x\n", cmd_no);
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 65d10a3..39f3176 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -1119,6 +1119,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
 	case HostCmd_CMD_TDLS_OPER:
 		ret = mwifiex_ret_tdls_oper(priv, resp);
 		break;
+	case HostCmd_CMD_CHAN_REPORT_REQUEST:
+		break;
 	default:
 		dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
 			resp->command);
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index baf5314..f5c2af0 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -761,6 +761,11 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
 		if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf))
 			return -1;
 		break;
+	case HostCmd_CMD_CHAN_REPORT_REQUEST:
+		if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf,
+							  data_buf))
+			return -1;
+		break;
 	default:
 		dev_err(priv->adapter->dev,
 			"PREP_CMD: unknown cmd %#x\n", cmd_no);
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 07/10] mwifiex: support for channel report for radar detection
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
                   ` (5 preceding siblings ...)
  2015-01-28 10:24 ` [PATCH v2 06/10] mwifiex: add cfg80211 start_radar_detection handler Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 08/10] mwifiex: handle radar detect event from FW Avinash Patil
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

This patch adds support for channel report enabling.
Channel report event happens if radar is detected on specified channel
after driver has issued radar detect command within CAC time.
Driver in turn sends RADAR_DETECTED event to cfg80211 to tell radar was
detected within CAC time.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/11h.c       | 51 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/mwifiex/fw.h        | 23 ++++++++++++++
 drivers/net/wireless/mwifiex/main.h      |  2 ++
 drivers/net/wireless/mwifiex/sta_event.c |  5 ++++
 drivers/net/wireless/mwifiex/uap_event.c |  4 +++
 5 files changed, 85 insertions(+)

diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c
index 8832c83..e44cac7 100644
--- a/drivers/net/wireless/mwifiex/11h.c
+++ b/drivers/net/wireless/mwifiex/11h.c
@@ -165,3 +165,54 @@ void mwifiex_abort_cac(struct mwifiex_private *priv)
 				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
 	}
 }
+
+/* This function handles channel report event from FW during CAC period.
+ * If radar is detected during CAC, driver indicates the same to cfg80211
+ * and also cancels ongoing delayed work.
+ */
+int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
+				     struct sk_buff *skb)
+{
+	struct host_cmd_ds_chan_rpt_event *rpt_event;
+	struct mwifiex_ie_types_chan_rpt_data *rpt;
+	u8 *evt_buf;
+	u16 event_len, tlv_len;
+
+	rpt_event = (void *)(skb->data + sizeof(u32));
+	event_len = skb->len - (sizeof(struct host_cmd_ds_chan_rpt_event)+
+				sizeof(u32));
+
+	if (le32_to_cpu(rpt_event->result) != HostCmd_RESULT_OK) {
+		dev_err(priv->adapter->dev, "Error in channel report event\n");
+		return -1;
+	}
+
+	evt_buf = (void *)&rpt_event->tlvbuf;
+
+	while (event_len >= sizeof(struct mwifiex_ie_types_header)) {
+		rpt = (void *)&rpt_event->tlvbuf;
+		tlv_len = le16_to_cpu(rpt->header.len);
+
+		switch (le16_to_cpu(rpt->header.type)) {
+		case TLV_TYPE_CHANRPT_11H_BASIC:
+			if (rpt->map.radar) {
+				dev_notice(priv->adapter->dev,
+					   "RADAR Detected on channel %d!\n",
+					    priv->dfs_chandef.chan->hw_value);
+				cancel_delayed_work_sync(&priv->dfs_cac_work);
+				cfg80211_cac_event(priv->netdev,
+						   &priv->dfs_chandef,
+						   NL80211_RADAR_DETECTED,
+						   GFP_KERNEL);
+			}
+			break;
+		default:
+			break;
+		}
+
+		evt_buf += (tlv_len + sizeof(rpt->header));
+		event_len -= (tlv_len + sizeof(rpt->header));
+	}
+
+	return 0;
+}
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 739151c..324ef29 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -158,6 +158,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define TLV_TYPE_POWER_GROUP        (PROPRIETARY_TLV_BASE_ID + 84)
 #define TLV_TYPE_BSS_SCAN_RSP       (PROPRIETARY_TLV_BASE_ID + 86)
 #define TLV_TYPE_BSS_SCAN_INFO      (PROPRIETARY_TLV_BASE_ID + 87)
+#define TLV_TYPE_CHANRPT_11H_BASIC  (PROPRIETARY_TLV_BASE_ID + 91)
 #define TLV_TYPE_UAP_RETRY_LIMIT    (PROPRIETARY_TLV_BASE_ID + 93)
 #define TLV_TYPE_WAPI_IE            (PROPRIETARY_TLV_BASE_ID + 94)
 #define TLV_TYPE_UAP_MGMT_FRAME     (PROPRIETARY_TLV_BASE_ID + 104)
@@ -494,6 +495,7 @@ enum P2P_MODES {
 #define EVENT_HOSTWAKE_STAIE		0x0000004d
 #define EVENT_CHANNEL_SWITCH_ANN        0x00000050
 #define EVENT_TDLS_GENERIC_EVENT        0x00000052
+#define EVENT_CHANNEL_REPORT_RDY        0x00000054
 #define EVENT_EXT_SCAN_REPORT           0x00000058
 #define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
 #define EVENT_TX_STATUS_REPORT		0x00000074
@@ -1228,6 +1230,13 @@ struct host_cmd_ds_chan_rpt_req {
 	__le32 msec_dwell_time;
 } __packed;
 
+struct host_cmd_ds_chan_rpt_event {
+	__le32 result;
+	__le64 start_tsf;
+	__le32 duration;
+	u8 tlvbuf[0];
+} __packed;
+
 struct mwifiex_fixed_bcn_param {
 	__le64 timestamp;
 	__le16 beacon_period;
@@ -1804,6 +1813,20 @@ struct mwifiex_ie_types_rssi_threshold {
 	u8 evt_freq;
 } __packed;
 
+struct meas_rpt_map {
+	u8 rssi:3;
+	u8 unmeasured:1;
+	u8 radar:1;
+	u8 unidentified_sig:1;
+	u8 ofdm_preamble:1;
+	u8 bss:1;
+} __packed;
+
+struct mwifiex_ie_types_chan_rpt_data {
+	struct mwifiex_ie_types_header header;
+	struct meas_rpt_map map;
+} __packed;
+
 struct host_cmd_ds_802_11_subsc_evt {
 	__le16 action;
 	__le16 events;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index e266d99..281a30a 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -1384,6 +1384,8 @@ void mwifiex_clean_auto_tdls(struct mwifiex_private *priv);
 int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
 					  struct host_cmd_ds_command *cmd,
 					  void *data_buf);
+int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
+				     struct sk_buff *skb);
 
 void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
 				   void *event_body);
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index c37e8cb..ad5c5e0 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -516,6 +516,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 		mwifiex_parse_tx_status_event(priv, adapter->event_body);
 		break;
 
+	case EVENT_CHANNEL_REPORT_RDY:
+		dev_dbg(adapter->dev, "event: Channel Report\n");
+		ret = mwifiex_11h_handle_chanrpt_ready(priv,
+						       adapter->event_skb);
+		break;
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
 			eventcause);
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 9b4ca6f..e0bdf6a 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -215,7 +215,11 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 		adapter->ps_state = PS_STATE_AWAKE;
 		adapter->pm_wakeup_card_req = false;
 		adapter->pm_wakeup_fw_try = false;
+		break;
 
+	case EVENT_CHANNEL_REPORT_RDY:
+		dev_dbg(adapter->dev, "event: Channel Report\n");
+		mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
 		break;
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 08/10] mwifiex: handle radar detect event from FW
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
                   ` (6 preceding siblings ...)
  2015-01-28 10:24 ` [PATCH v2 07/10] mwifiex: support for channel report for radar detection Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 09/10] mwifiex: channel switch support for mwifiex Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 10/10] mwifiex: 11h handling for AP interface Avinash Patil
  9 siblings, 0 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

This patch adds support for radar_detected event from FW.
Driver in turn would stop netdev queues to stop TX traffic and
issue RADAR_DETECT event to cfg80211.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/11h.c       | 24 ++++++++++++++++++++++++
 drivers/net/wireless/mwifiex/fw.h        | 20 ++++++++++++++++++++
 drivers/net/wireless/mwifiex/main.h      |  2 ++
 drivers/net/wireless/mwifiex/sta_event.c |  5 +++++
 drivers/net/wireless/mwifiex/uap_event.c |  4 ++++
 5 files changed, 55 insertions(+)

diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c
index e44cac7..08c12ae 100644
--- a/drivers/net/wireless/mwifiex/11h.c
+++ b/drivers/net/wireless/mwifiex/11h.c
@@ -216,3 +216,27 @@ int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
 
 	return 0;
 }
+
+/* Handler for radar detected event from FW.*/
+int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
+				      struct sk_buff *skb)
+{
+	struct mwifiex_radar_det_event *rdr_event;
+
+	rdr_event = (void *)(skb->data + sizeof(u32));
+
+	if (le32_to_cpu(rdr_event->passed)) {
+		dev_notice(priv->adapter->dev,
+			   "radar detected; indicating kernel\n");
+		cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef,
+				     GFP_KERNEL);
+		dev_dbg(priv->adapter->dev, "regdomain: %d\n",
+			rdr_event->reg_domain);
+		dev_dbg(priv->adapter->dev, "radar detection type: %d\n",
+			rdr_event->det_type);
+	} else {
+		dev_dbg(priv->adapter->dev, "false radar detection event!\n");
+	}
+
+	return 0;
+}
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 324ef29..6d433227 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -495,6 +495,7 @@ enum P2P_MODES {
 #define EVENT_HOSTWAKE_STAIE		0x0000004d
 #define EVENT_CHANNEL_SWITCH_ANN        0x00000050
 #define EVENT_TDLS_GENERIC_EVENT        0x00000052
+#define EVENT_RADAR_DETECTED		0x00000053
 #define EVENT_CHANNEL_REPORT_RDY        0x00000054
 #define EVENT_EXT_SCAN_REPORT           0x00000058
 #define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
@@ -1813,6 +1814,25 @@ struct mwifiex_ie_types_rssi_threshold {
 	u8 evt_freq;
 } __packed;
 
+#define MWIFIEX_DFS_REC_HDR_LEN		8
+#define MWIFIEX_DFS_REC_HDR_NUM		10
+#define MWIFIEX_BIN_COUNTER_LEN		7
+
+struct mwifiex_radar_det_event {
+	__le32 detect_count;
+	u8 reg_domain;  /*1=fcc, 2=etsi, 3=mic*/
+	u8 det_type;  /*0=none, 1=pw(chirp), 2=pri(radar)*/
+	__le16 pw_chirp_type;
+	u8 pw_chirp_idx;
+	u8 pw_value;
+	u8 pri_radar_type;
+	u8 pri_bincnt;
+	u8 bin_counter[MWIFIEX_BIN_COUNTER_LEN];
+	u8 num_dfs_records;
+	u8 dfs_record_hdr[MWIFIEX_DFS_REC_HDR_NUM][MWIFIEX_DFS_REC_HDR_LEN];
+	__le32 passed;
+} __packed;
+
 struct meas_rpt_map {
 	u8 rssi:3;
 	u8 unmeasured:1;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 281a30a..ad9d679 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -1395,6 +1395,8 @@ mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
 				struct sk_buff *skb, u8 flag, u64 *cookie);
 void mwifiex_dfs_cac_work_queue(struct work_struct *work);
 void mwifiex_abort_cac(struct mwifiex_private *priv);
+int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
+				      struct sk_buff *skb);
 
 void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr,
 			   s8 nflr);
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index ad5c5e0..c03b82c 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -521,6 +521,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 		ret = mwifiex_11h_handle_chanrpt_ready(priv,
 						       adapter->event_skb);
 		break;
+	case EVENT_RADAR_DETECTED:
+		dev_dbg(adapter->dev, "event: Radar detected\n");
+		ret = mwifiex_11h_handle_radar_detected(priv,
+							adapter->event_skb);
+		break;
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
 			eventcause);
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index e0bdf6a..f4794cd 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -221,6 +221,10 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 		dev_dbg(adapter->dev, "event: Channel Report\n");
 		mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
 		break;
+	case EVENT_RADAR_DETECTED:
+		dev_dbg(adapter->dev, "event: Radar detected\n");
+		mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
+		break;
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
 			eventcause);
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 09/10] mwifiex: channel switch support for mwifiex
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
                   ` (7 preceding siblings ...)
  2015-01-28 10:24 ` [PATCH v2 08/10] mwifiex: handle radar detect event from FW Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  2015-01-28 10:24 ` [PATCH v2 10/10] mwifiex: 11h handling for AP interface Avinash Patil
  9 siblings, 0 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

This patch adds cfg80211 channel_switch support for mwifiex.
Upon receiving channel switch request, driver would parse channel
switch announcement IE from beacon_data.
If TX is blocked, netdev queues are stopped. IEs from csa_beacon
are then parsed and set to FW.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 drivers/net/wireless/mwifiex/11h.c      | 37 ++++++++++++++
 drivers/net/wireless/mwifiex/cfg80211.c | 85 ++++++++++++++++++++++++++++++++-
 drivers/net/wireless/mwifiex/ie.c       | 12 ++++-
 drivers/net/wireless/mwifiex/main.h     |  5 ++
 4 files changed, 136 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c
index 08c12ae..d794686 100644
--- a/drivers/net/wireless/mwifiex/11h.c
+++ b/drivers/net/wireless/mwifiex/11h.c
@@ -240,3 +240,40 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
 
 	return 0;
 }
+
+/* This is work queue function for channel switch handling.
+ * This function takes care of updating new channel definitin to
+ * bss config structure, restart AP and indicate channel switch success
+ * to cfg80211.
+ */
+void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
+{
+	struct mwifiex_uap_bss_param *bss_cfg;
+	struct delayed_work *delayed_work =
+			container_of(work, struct delayed_work, work);
+	struct mwifiex_private *priv =
+			container_of(delayed_work, struct mwifiex_private,
+				     dfs_chan_sw_work);
+
+	if (WARN_ON(!priv))
+		return;
+
+	bss_cfg = &priv->bss_cfg;
+	if (!bss_cfg->beacon_period) {
+		dev_err(priv->adapter->dev,
+			"channel switch: AP already stopped\n");
+		return;
+	}
+
+	mwifiex_uap_set_channel(bss_cfg, priv->dfs_chandef);
+
+	if (mwifiex_config_start_uap(priv, bss_cfg)) {
+		dev_dbg(priv->adapter->dev,
+			"Failed to start AP after channel switch\n");
+		return;
+	}
+
+	dev_notice(priv->adapter->dev,
+		   "indicating channel switch completion to kernel\n");
+	cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef);
+}
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 7a969fd..2d1ea93 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2399,7 +2399,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 	struct mwifiex_private *priv;
 	struct net_device *dev;
 	void *mdev_priv;
-	char dfs_cac_str[MWIFIEX_MAX_WQ_LEN];
+	char dfs_cac_str[MWIFIEX_MAX_WQ_LEN], dfs_chsw_str[MWIFIEX_MAX_WQ_LEN];
 
 	if (!adapter)
 		return ERR_PTR(-EFAULT);
@@ -2582,6 +2582,24 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 
 	INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
 
+	strcpy(dfs_chsw_str, "MWIFIEX_DFS_CHSW");
+	strcat(dfs_chsw_str, name);
+	priv->dfs_chan_sw_workqueue = alloc_workqueue(dfs_chsw_str,
+						      WQ_HIGHPRI | WQ_UNBOUND |
+						      WQ_MEM_RECLAIM, 1);
+	if (!priv->dfs_chan_sw_workqueue) {
+		wiphy_err(wiphy, "cannot register virtual network device\n");
+		free_netdev(dev);
+		priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
+		priv->netdev = NULL;
+		memset(&priv->wdev, 0, sizeof(priv->wdev));
+		priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
+		return ERR_PTR(-ENOMEM);
+	}
+
+	INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
+			  mwifiex_dfs_chan_sw_work_queue);
+
 	sema_init(&priv->async_sem, 1);
 
 	dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
@@ -2637,6 +2655,11 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 		priv->dfs_cac_workqueue = NULL;
 	}
 
+	if (priv->dfs_chan_sw_workqueue) {
+		flush_workqueue(priv->dfs_chan_sw_workqueue);
+		destroy_workqueue(priv->dfs_chan_sw_workqueue);
+		priv->dfs_chan_sw_workqueue = NULL;
+	}
 	/* Clear the priv in adapter */
 	priv->netdev->ieee80211_ptr = NULL;
 	priv->netdev = NULL;
@@ -3116,6 +3139,62 @@ mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int
+mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+				struct cfg80211_csa_settings *params)
+{
+	struct ieee_types_header *chsw_ie;
+	struct ieee80211_channel_sw_ie *channel_sw;
+	int chsw_msec;
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+	if (priv->adapter->scan_processing) {
+		dev_err(priv->adapter->dev,
+			"radar detection: scan in process...\n");
+		return -EBUSY;
+	}
+
+	if (priv->wdev.cac_started)
+		return -EBUSY;
+
+	if (cfg80211_chandef_identical(&params->chandef,
+				       &priv->dfs_chandef))
+		return -EINVAL;
+
+	chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,
+					   params->beacon_csa.tail,
+					   params->beacon_csa.tail_len);
+	if (!chsw_ie) {
+		dev_err(priv->adapter->dev,
+			"Could not parse channel switch announcement IE\n");
+		return -EINVAL;
+	}
+
+	channel_sw = (void *)(chsw_ie + 1);
+	if (channel_sw->mode) {
+		if (netif_carrier_ok(priv->netdev))
+			netif_carrier_off(priv->netdev);
+		mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
+	}
+
+	if (mwifiex_del_mgmt_ies(priv))
+		wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
+
+	if (mwifiex_set_mgmt_ies(priv, &params->beacon_csa)) {
+		wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__);
+		return -EFAULT;
+	}
+
+	memcpy(&priv->dfs_chandef, &params->chandef, sizeof(priv->dfs_chandef));
+	memcpy(&priv->beacon_after, &params->beacon_after,
+	       sizeof(priv->beacon_after));
+
+	chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100);
+	queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work,
+			   msecs_to_jiffies(chsw_msec));
+	return 0;
+}
+
+static int
 mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
 				       struct net_device *dev,
 				       struct cfg80211_chan_def *chandef,
@@ -3210,6 +3289,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
 	.add_station = mwifiex_cfg80211_add_station,
 	.change_station = mwifiex_cfg80211_change_station,
 	.start_radar_detection = mwifiex_cfg80211_start_radar_detection,
+	.channel_switch = mwifiex_cfg80211_channel_switch,
 };
 
 #ifdef CONFIG_PM
@@ -3313,7 +3393,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
 	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
 			WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
 			WIPHY_FLAG_AP_UAPSD |
-			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+			WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
 	if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
 		wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c
index a6af7b8..f3b6ed2 100644
--- a/drivers/net/wireless/mwifiex/ie.c
+++ b/drivers/net/wireless/mwifiex/ie.c
@@ -325,6 +325,7 @@ static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv,
 {
 	struct mwifiex_ie *gen_ie;
 	struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL;
+	struct ieee_types_header *chsw_ie = NULL;
 	u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
 	const u8 *vendor_ie;
 
@@ -356,9 +357,18 @@ static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv,
 			ie_len += wpa_ie->len + 2;
 			gen_ie->ie_length = cpu_to_le16(ie_len);
 		}
+
+		chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,
+						   info->tail, info->tail_len);
+		if (chsw_ie) {
+			memcpy(gen_ie->ie_buffer + ie_len,
+			       chsw_ie, chsw_ie->len + 2);
+			ie_len += chsw_ie->len + 2;
+			gen_ie->ie_length = cpu_to_le16(ie_len);
+		}
 	}
 
-	if (rsn_ie || wpa_ie) {
+	if (rsn_ie || wpa_ie || chsw_ie) {
 		if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL,
 						 NULL, NULL, NULL)) {
 			kfree(gen_ie);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index ad9d679..599698c 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -591,6 +591,10 @@ struct mwifiex_private {
 	struct cfg80211_chan_def dfs_chandef;
 	struct workqueue_struct *dfs_cac_workqueue;
 	struct delayed_work dfs_cac_work;
+	struct timer_list dfs_chan_switch_timer;
+	struct workqueue_struct *dfs_chan_sw_workqueue;
+	struct delayed_work dfs_chan_sw_work;
+	struct cfg80211_beacon_data beacon_after;
 };
 
 enum mwifiex_ba_status {
@@ -1394,6 +1398,7 @@ struct sk_buff *
 mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
 				struct sk_buff *skb, u8 flag, u64 *cookie);
 void mwifiex_dfs_cac_work_queue(struct work_struct *work);
+void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work);
 void mwifiex_abort_cac(struct mwifiex_private *priv);
 int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
 				      struct sk_buff *skb);
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 10/10] mwifiex: 11h handling for AP interface
  2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
                   ` (8 preceding siblings ...)
  2015-01-28 10:24 ` [PATCH v2 09/10] mwifiex: channel switch support for mwifiex Avinash Patil
@ 2015-01-28 10:24 ` Avinash Patil
  9 siblings, 0 replies; 12+ messages in thread
From: Avinash Patil @ 2015-01-28 10:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: akarwar, cluo, gaoqs, Avinash Patil

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 <patila@marvell.com>
Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
---
 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


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [v2, 01/10] mwifiex: do not send regulatory update while starting AP
  2015-01-28 10:24 ` [PATCH v2 01/10] mwifiex: do not send regulatory update while starting AP Avinash Patil
@ 2015-01-29  8:26   ` Kalle Valo
  0 siblings, 0 replies; 12+ messages in thread
From: Kalle Valo @ 2015-01-29  8:26 UTC (permalink / raw)
  To: Avinash Patil; +Cc: linux-wireless, akarwar, cluo, gaoqs, Avinash Patil


> When regulatory domain changes, cfg80211 already issues request
> to change regulatory domain to driver via reg_notifier.
> There is no need to set regulatory again during start_ap.
> 
> Signed-off-by: Avinash Patil <patila@marvell.com>
> Signed-off-by: Qingshui Gao <gaoqs@marvell.com>
> Signed-off-by: Cathy Luo <cluo@marvell.com>

Thanks, 10 patches applied to wireless-drivers-next.git:

6144369f8b4b mwifiex: do not send regulatory update while starting AP
35c739b50d78 mwifiex: store AP configuration in private structure
b0d4c5ec9730 mwifiex: update IEs after AP has started
b654ca182a2f mwifiex: refactor start_ap handler
2ade5667e2e0 mwifiex: separate function for parsing head and tail IEs
85afb18621be mwifiex: add cfg80211 start_radar_detection handler
0a694d68651b mwifiex: support for channel report for radar detection
3b57c1a713a9 mwifiex: handle radar detect event from FW
7d652034d1a0 mwifiex: channel switch support for mwifiex
cf075eac9ca9 mwifiex: 11h handling for AP interface

Kalle Valo

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2015-01-29  8:26 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-28 10:24 [PATCH v2 00/10] mwifiex: DFS support for mwifiex AP Avinash Patil
2015-01-28 10:24 ` [PATCH v2 01/10] mwifiex: do not send regulatory update while starting AP Avinash Patil
2015-01-29  8:26   ` [v2, " Kalle Valo
2015-01-28 10:24 ` [PATCH v2 02/10] mwifiex: store AP configuration in private structure Avinash Patil
2015-01-28 10:24 ` [PATCH v2 03/10] mwifiex: update IEs after AP has started Avinash Patil
2015-01-28 10:24 ` [PATCH v2 04/10] mwifiex: refactor start_ap handler Avinash Patil
2015-01-28 10:24 ` [PATCH v2 05/10] mwifiex: separate function for parsing head and tail IEs Avinash Patil
2015-01-28 10:24 ` [PATCH v2 06/10] mwifiex: add cfg80211 start_radar_detection handler Avinash Patil
2015-01-28 10:24 ` [PATCH v2 07/10] mwifiex: support for channel report for radar detection Avinash Patil
2015-01-28 10:24 ` [PATCH v2 08/10] mwifiex: handle radar detect event from FW Avinash Patil
2015-01-28 10:24 ` [PATCH v2 09/10] mwifiex: channel switch support for mwifiex Avinash Patil
2015-01-28 10:24 ` [PATCH v2 10/10] mwifiex: 11h handling for AP interface Avinash Patil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).