Search Linux Wireless

RE: [PATCH v2] wifi: nxpwifi: fix firmware crash for AP DFS mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sorry. It should be "wifi: mwifiex: ...". I will submit correct one later.
> From: David Lin <yu-hao.lin@xxxxxxx>
> Sent: Wednesday, October 9, 2024 2:07 PM
> To: linux-wireless@xxxxxxxxxxxxxxx
> Cc: linux-kernel@xxxxxxxxxxxxxxx; briannorris@xxxxxxxxxxxx;
> kvalo@xxxxxxxxxx; francesco@xxxxxxxxxx; Pete Hsieh
> <tsung-hsien.hsieh@xxxxxxx>; s.hauer@xxxxxxxxxxxxxx; David Lin
> <yu-hao.lin@xxxxxxx>
> Subject: [PATCH v2] wifi: nxpwifi: fix firmware crash for AP DFS mode
> 
> 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@xxxxxxx>
> ---
> 
> 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(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c
> b/drivers/net/wireless/marvell/mwifiex/11h.c
> index 032b93a41d99..3d8f6c610bca 100644
> --- a/drivers/net/wireless/marvell/mwifiex/11h.c
> +++ b/drivers/net/wireless/marvell/mwifiex/11h.c
> @@ -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;
> +	}
>  }
> diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> index fca3eea7ee84..40f51e62b2e7 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
> @@ -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 = &params->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,
> +&params->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, &params->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; diff --git
> a/drivers/net/wireless/marvell/mwifiex/cfg80211.h
> b/drivers/net/wireless/marvell/mwifiex/cfg80211.h
> index 50f7001f5ef0..0a12437f89f2 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.h
> +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.h
> @@ -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
> diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h
> b/drivers/net/wireless/marvell/mwifiex/decl.h
> index 84603f1e7f6e..9ece61743b9c 100644
> --- a/drivers/net/wireless/marvell/mwifiex/decl.h
> +++ b/drivers/net/wireless/marvell/mwifiex/decl.h
> @@ -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
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.h
> b/drivers/net/wireless/marvell/mwifiex/main.h
> index 566adce3413c..58e8a3daba4a 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.h
> +++ b/drivers/net/wireless/marvell/mwifiex/main.h
> @@ -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;
> 
> base-commit: 5a4d42c1688c88f3be6aef46b0ea6c32694cd2b8
> --
> 2.34.1






[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux