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
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 <[email protected]>
Signed-off-by: Qingshui Gao <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
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 37041fb..468f0d8 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 d6a0411..cf61775 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -568,7 +568,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
On Fri, 2015-01-23 at 11:00 -0800, Kalle Valo wrote:
> Avinash Patil <[email protected]> writes:
>
> > 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
>
> Patch 5 had conflicts, please rebase.
>
Hi Kalle,
I will rebase patches on top of master and resend.
Thanks,
Avinash
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 <[email protected]>
Signed-off-by: Qingshui Gao <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
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 8e2b692..26380a5 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 0482116..c5899dd 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -513,6 +513,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 ec40be8..6bb7b27 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -216,7 +216,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
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 <[email protected]>
Signed-off-by: Qingshui Gao <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
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 6143625..9ef9ff6 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1675,7 +1675,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;
@@ -1695,6 +1694,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:
@@ -1710,31 +1714,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)) {
@@ -1758,23 +1738,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;
}
@@ -1784,23 +1749,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 fb8e195..d6a0411 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
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 72dd1f3..dc1be72 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1740,6 +1740,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, ¶ms->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);
@@ -3176,6 +3188,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 b021701..f4087bf 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -140,6 +140,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 0163fcb..c120141 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -596,6 +596,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
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 <[email protected]>
Signed-off-by: Qingshui Gao <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
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 9ef9ff6..13c9c67 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1649,6 +1649,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");
@@ -2381,6 +2383,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
*/
@@ -2394,6 +2397,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);
@@ -2558,6 +2562,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);
@@ -2607,6 +2629,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;
@@ -3055,6 +3083,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)
@@ -3118,6 +3176,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 d54c576..b021701 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -664,6 +664,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 cf61775..8e2b692 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -589,6 +589,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 {
@@ -755,6 +758,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
Avinash Patil <[email protected]> writes:
> 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
Patch 5 had conflicts, please rebase.
--
Kalle Valo
Store AP configuration in private structure so that we know
current AP configuration.
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/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 85795f9..9dde975 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1653,6 +1653,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)) {
@@ -1780,6 +1781,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 0f5fcdf..fb8e195 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -578,6 +578,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
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 <[email protected]>
Signed-off-by: Qingshui Gao <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
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 13c9c67..72dd1f3 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2397,7 +2397,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);
@@ -2580,6 +2580,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);
@@ -2635,6 +2653,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;
@@ -3083,6 +3106,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(¶ms->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, ¶ms->beacon_csa)) {
+ wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__);
+ return -EFAULT;
+ }
+
+ memcpy(&priv->dfs_chandef, ¶ms->chandef, sizeof(priv->dfs_chandef));
+ memcpy(&priv->beacon_after, ¶ms->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,
@@ -3177,6 +3256,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
@@ -3280,7 +3360,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 1a612f6..0163fcb 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -592,6 +592,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
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 <[email protected]>
Signed-off-by: Qingshui Gao <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
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 26380a5..1a612f6 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 c5899dd..37ade9c 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -518,6 +518,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 6bb7b27..01303f1 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -222,6 +222,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
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 <[email protected]>
Signed-off-by: Qingshui Gao <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
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 9dde975..6143625 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1679,8 +1679,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, ¶ms->beacon))
- return -1;
bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
if (!bss_cfg)
@@ -1781,6 +1779,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
return -1;
}
+ if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon))
+ return -1;
+
memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
kfree(bss_cfg);
--
1.8.1.4
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 <[email protected]>
Signed-off-by: Qingshui Gao <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
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 56e50d6..85795f9 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1737,7 +1737,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