@@ -7,7 +7,7 @@
#include "main.h"
#include "fw.h"
-
+#include "cfg80211.h"
void mwifiex_init_11h_params(struct mwifiex_private *priv)
{
@@ -221,8 +221,11 @@ int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
cancel_delayed_work_sync(&priv->dfs_cac_work);
cfg80211_cac_event(priv->netdev,
&priv->dfs_chandef,
- NL80211_RADAR_DETECTED,
+ NL80211_RADAR_CAC_ABORTED,
GFP_KERNEL, 0);
+ cfg80211_radar_event(priv->adapter->wiphy,
+ &priv->dfs_chandef,
+ GFP_KERNEL);
}
break;
default:
@@ -245,9 +248,16 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
mwifiex_dbg(priv->adapter, MSG,
"radar detected; indicating kernel\n");
- if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
- mwifiex_dbg(priv->adapter, ERROR,
- "Failed to stop CAC in FW\n");
+
+ if (priv->wdev.links[0].cac_started) {
+ if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
+ mwifiex_dbg(priv->adapter, ERROR,
+ "Failed to stop CAC in FW\n");
+ cancel_delayed_work_sync(&priv->dfs_cac_work);
+ cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
+ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0);
+ }
+
cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef,
GFP_KERNEL);
mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n",
@@ -268,8 +278,12 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
struct mwifiex_uap_bss_param *bss_cfg;
struct delayed_work *delayed_work = to_delayed_work(work);
struct mwifiex_private *priv =
- container_of(delayed_work, struct mwifiex_private,
- dfs_chan_sw_work);
+ container_of(delayed_work, struct mwifiex_private,
+ dfs_chan_sw_work);
+
+ if (mwifiex_del_mgmt_ies(priv))
+ mwifiex_dbg(priv->adapter, ERROR,
+ "Failed to delete mgmt IEs!\n");
bss_cfg = &priv->bss_cfg;
if (!bss_cfg->beacon_period) {
@@ -278,6 +292,21 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
return;
}
+ if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
+ HostCmd_ACT_GEN_SET, 0, NULL, true)) {
+ mwifiex_dbg(priv->adapter, ERROR,
+ "channel switch: Failed to stop the BSS\n");
+ return;
+ }
+
+ if (mwifiex_cfg80211_change_beacon_data(priv->adapter->wiphy,
+ priv->netdev,
+ &priv->beacon_after)) {
+ mwifiex_dbg(priv->adapter, ERROR,
+ "channel switch: Failed to set beacon\n");
+ return;
+ }
+
mwifiex_uap_set_channel(priv, bss_cfg, priv->dfs_chandef);
if (mwifiex_config_start_uap(priv, bss_cfg)) {
@@ -291,4 +320,10 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
wiphy_lock(priv->wdev.wiphy);
cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef, 0);
wiphy_unlock(priv->wdev.wiphy);
+
+ if (priv->uap_stop_tx) {
+ netif_carrier_on(priv->netdev);
+ mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter);
+ priv->uap_stop_tx = false;
+ }
}
@@ -1858,16 +1858,12 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
return 0;
}
-/* cfg80211 operation handler for change_beacon.
- * Function retrieves and sets modified management IEs to FW.
- */
-static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
- struct net_device *dev,
- struct cfg80211_ap_update *params)
+int mwifiex_cfg80211_change_beacon_data(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_beacon_data *data)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct mwifiex_adapter *adapter = priv->adapter;
- struct cfg80211_beacon_data *data = ¶ms->beacon;
mwifiex_cancel_scan(adapter);
@@ -1877,12 +1873,6 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
return -EINVAL;
}
- if (!priv->bss_started) {
- mwifiex_dbg(priv->adapter, ERROR,
- "%s: bss not started\n", __func__);
- return -EINVAL;
- }
-
if (mwifiex_set_mgmt_ies(priv, data)) {
mwifiex_dbg(priv->adapter, ERROR,
"%s: setting mgmt ies failed\n", __func__);
@@ -1892,6 +1882,16 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
return 0;
}
+/* cfg80211 operation handler for change_beacon.
+ * Function retrieves and sets modified management IEs to FW.
+ */
+static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_ap_update *params)
+{
+ return mwifiex_cfg80211_change_beacon_data(wiphy, dev, ¶ms->beacon);
+}
+
/* cfg80211 operation handler for del_station.
* Function deauthenticates station which value is provided in mac parameter.
* If mac is NULL/broadcast, all stations in associated station list are
@@ -4027,10 +4027,8 @@ 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);
+ int chsw_msec;
if (priv->adapter->scan_processing) {
mwifiex_dbg(priv->adapter, ERROR,
@@ -4045,20 +4043,10 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
&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) {
- mwifiex_dbg(priv->adapter, ERROR,
- "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);
+ if (params->block_tx) {
+ netif_carrier_off(priv->netdev);
mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
+ priv->uap_stop_tx = true;
}
if (mwifiex_del_mgmt_ies(priv))
@@ -4075,7 +4063,7 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
memcpy(&priv->beacon_after, ¶ms->beacon_after,
sizeof(priv->beacon_after));
- chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100);
+ chsw_msec = max(params->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;
@@ -4814,6 +4802,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
WIPHY_FLAG_HAS_CHANNEL_SWITCH |
WIPHY_FLAG_NETNS_OK |
WIPHY_FLAG_PS_ON_BY_DEFAULT;
+ wiphy->max_num_csa_counters = MWIFIEX_MAX_CSA_COUNTERS;
if (adapter->host_mlme_enabled)
wiphy->flags |= WIPHY_FLAG_REPORTS_OBSS;
@@ -13,5 +13,7 @@
#include "main.h"
int mwifiex_register_cfg80211(struct mwifiex_adapter *);
-
+int mwifiex_cfg80211_change_beacon_data(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_beacon_data *data);
#endif
@@ -19,6 +19,7 @@
#define MWIFIEX_BSS_COEX_COUNT 2
#define MWIFIEX_MAX_BSS_NUM (3)
+#define MWIFIEX_MAX_CSA_COUNTERS 5
#define MWIFIEX_DMA_ALIGN_SZ 64
#define MWIFIEX_RX_HEADROOM 64
@@ -678,6 +678,7 @@ struct mwifiex_private {
struct delayed_work dfs_cac_work;
struct workqueue_struct *dfs_chan_sw_workqueue;
struct delayed_work dfs_chan_sw_work;
+ bool uap_stop_tx;
struct cfg80211_beacon_data beacon_after;
struct mwifiex_11h_intf_state state_11h;
struct mwifiex_ds_mem_rw mem_rw;
When AP mode is running on DFS channel and radar detection happened during or after CAC, firmware will crash due to the code of mwifiex is too old to handle DFS process. This patch fixes above issue and had been tested with IW416. Signed-off-by: David Lin <yu-hao.lin@nxp.com> --- v2: - remove clean up for adapter (from priv->adapter to adapter). - remove useless check of netif_carrier_ok(). - just return directly for mwifiex_cfg80211_change_beacon(). - remove debugfs file "fake_radar_detect". --- drivers/net/wireless/marvell/mwifiex/11h.c | 49 ++++++++++++++++--- .../net/wireless/marvell/mwifiex/cfg80211.c | 49 +++++++------------ .../net/wireless/marvell/mwifiex/cfg80211.h | 4 +- drivers/net/wireless/marvell/mwifiex/decl.h | 1 + drivers/net/wireless/marvell/mwifiex/main.h | 1 + 5 files changed, 66 insertions(+), 38 deletions(-) base-commit: 5a4d42c1688c88f3be6aef46b0ea6c32694cd2b8