diff options
| author | Kalle Valo <kvalo@kernel.org> | 2022-10-29 08:25:50 +0300 | 
|---|---|---|
| committer | Kalle Valo <kvalo@kernel.org> | 2022-10-29 08:25:50 +0300 | 
| commit | a9501019f2de706eb43b59d66dcde70a23440cd3 (patch) | |
| tree | faf4f1b8a7c8bc9eed229ac690bcb953fd604995 | |
| parent | 637639cbfebb747406b9a57befc0b347057a3a24 (diff) | |
| parent | f3ca72b0327101a074a871539e61775d43908ca4 (diff) | |
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v6.2. Major changes:
ath11k
* support configuring channel dwell time during scan
| -rw-r--r-- | drivers/net/wireless/ath/ar5523/ar5523.c | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/core.c | 16 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/htc.c | 9 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/htt.h | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/hw.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi-tlv.c | 7 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/core.c | 9 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/core.h | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/mac.c | 222 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/pcic.c | 13 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/qmi.c | 12 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/reg.c | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/wmi.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/Makefile | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/hif_usb.c | 46 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/mci.c | 8 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/Makefile | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/wlan.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/debugfs.c | 36 | 
19 files changed, 268 insertions, 147 deletions
| diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index a184c09d2f0f..19f61225a708 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c @@ -241,6 +241,11 @@ static void ar5523_cmd_tx_cb(struct urb *urb)  	}  } +static void ar5523_cancel_tx_cmd(struct ar5523 *ar) +{ +	usb_kill_urb(ar->tx_cmd.urb_tx); +} +  static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,  		      int ilen, void *odata, int olen, int flags)  { @@ -280,6 +285,7 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,  	}  	if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) { +		ar5523_cancel_tx_cmd(ar);  		cmd->odata = NULL;  		ar5523_err(ar, "timeout waiting for command %02x reply\n",  			   code); diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 400f332a7ff0..5eb131ab916f 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -99,6 +99,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA988X_HW_2_0_VERSION, @@ -138,6 +139,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA9887_HW_1_0_VERSION, @@ -178,6 +180,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA6174_HW_3_2_VERSION, @@ -213,6 +216,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = true,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA6174_HW_2_1_VERSION, @@ -252,6 +256,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA6174_HW_2_1_VERSION, @@ -291,6 +296,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA6174_HW_3_0_VERSION, @@ -330,6 +336,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA6174_HW_3_2_VERSION, @@ -373,6 +380,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = true,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA99X0_HW_2_0_DEV_VERSION, @@ -418,6 +426,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA9984_HW_1_0_DEV_VERSION, @@ -470,6 +479,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA9888_HW_2_0_DEV_VERSION, @@ -519,6 +529,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA9377_HW_1_0_DEV_VERSION, @@ -558,6 +569,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA9377_HW_1_1_DEV_VERSION, @@ -599,6 +611,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA9377_HW_1_1_DEV_VERSION, @@ -631,6 +644,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = QCA4019_HW_1_0_DEV_VERSION, @@ -677,6 +691,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = false,  		.hw_restart_disconnect = false,  		.use_fw_tx_credits = true, +		.delay_unmap_buffer = false,  	},  	{  		.id = WCN3990_HW_1_0_DEV_VERSION, @@ -709,6 +724,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {  		.dynamic_sar_support = true,  		.hw_restart_disconnect = true,  		.use_fw_tx_credits = false, +		.delay_unmap_buffer = true,  	},  }; diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 6d1784f74bea..5bfeecb95fca 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -56,6 +56,15 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,  	ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,  		   ep->eid, skb); +	/* A corner case where the copy completion is reaching to host but still +	 * copy engine is processing it due to which host unmaps corresponding +	 * memory and causes SMMU fault, hence as workaround adding delay +	 * the unmapping memory to avoid SMMU faults. +	 */ +	if (ar->hw_params.delay_unmap_buffer && +	    ep->ul_pipe_id == 3) +		mdelay(2); +  	hdr = (struct ath10k_htc_hdr *)skb->data;  	ath10k_htc_restore_tx_skb(ep->htc, skb); diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index f06cf39204e2..c051a22fce14 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1108,8 +1108,10 @@ struct htt_rx_in_ord_ind {  	u8 reserved;  	__le16 msdu_count;  	union { -		struct htt_rx_in_ord_msdu_desc msdu_descs32[0]; -		struct htt_rx_in_ord_msdu_desc_ext msdu_descs64[0]; +		DECLARE_FLEX_ARRAY(struct htt_rx_in_ord_msdu_desc, +				   msdu_descs32); +		DECLARE_FLEX_ARRAY(struct htt_rx_in_ord_msdu_desc_ext, +				   msdu_descs64);  	} __packed;  } __packed; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 1b99f3a39a11..9643031a4427 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -637,6 +637,8 @@ struct ath10k_hw_params {  	bool hw_restart_disconnect;  	bool use_fw_tx_credits; + +	bool delay_unmap_buffer;  };  struct htt_resp; diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 876410a47d1d..6b6aa3c36744 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -584,7 +584,14 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)  			ath10k_warn(ar, "did not find station from tdls peer event");  			goto exit;  		} +  		arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id)); +		if (!arvif) { +			ath10k_warn(ar, "no vif for vdev_id %d found", +				    __le32_to_cpu(ev->vdev_id)); +			goto exit; +		} +  		ieee80211_tdls_oper_request(  					arvif->vif, station->addr,  					NL80211_TDLS_TEARDOWN, diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index b99180bc8172..0ab2f190f1ec 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1641,7 +1641,7 @@ static void ath11k_update_11d(struct work_struct *work)  	}  } -static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) +void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)  {  	struct ath11k *ar;  	struct ath11k_pdev *pdev; @@ -1677,6 +1677,10 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)  			     ath11k_mac_tx_mgmt_pending_free, ar);  		idr_destroy(&ar->txmgmt_idr);  		wake_up(&ar->txmgmt_empty_waitq); + +		ar->monitor_vdev_id = -1; +		clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags); +		clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);  	}  	wake_up(&ab->wmi_ab.tx_credits_wq); @@ -1730,9 +1734,6 @@ static void ath11k_core_restart(struct work_struct *work)  	struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);  	int ret; -	if (!ab->is_reset) -		ath11k_core_pre_reconfigure_recovery(ab); -  	ret = ath11k_core_reconfigure_on_crash(ab);  	if (ret) {  		ath11k_err(ab, "failed to reconfigure driver on crash recovery\n"); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index cf2f52cc4e30..22460b0abf03 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -505,6 +505,8 @@ struct ath11k_sta {  	u64 ps_start_jiffies;  	u64 ps_total_duration;  	bool peer_current_ps_valid; + +	u32 bw_prev;  };  #define ATH11K_MIN_5G_FREQ 4150 @@ -1157,6 +1159,7 @@ int ath11k_core_check_smbios(struct ath11k_base *ab);  void ath11k_core_halt(struct ath11k *ar);  int ath11k_core_resume(struct ath11k_base *ab);  int ath11k_core_suspend(struct ath11k_base *ab); +void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab);  const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,  						    const char *filename); diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 3cbcbb93a1a7..6426a38f8961 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -241,7 +241,10 @@ const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default = {  #define ath11k_a_rates (ath11k_legacy_rates + 4)  #define ath11k_a_rates_size (ARRAY_SIZE(ath11k_legacy_rates) - 4) -#define ATH11K_MAC_SCAN_TIMEOUT_MSECS 200 /* in msecs */ +#define ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD		200 /* in msecs */ + +/* Overhead due to the processing of channel switch events from FW */ +#define ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD	10 /* in msecs */  static const u32 ath11k_smps_map[] = {  	[WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC, @@ -3612,6 +3615,7 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,  	struct scan_req_params arg;  	int ret = 0;  	int i; +	u32 scan_timeout;  	mutex_lock(&ar->conf_mutex); @@ -3681,6 +3685,26 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,  		ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask);  	} +	/* if duration is set, default dwell times will be overwritten */ +	if (req->duration) { +		arg.dwell_time_active = req->duration; +		arg.dwell_time_active_2g = req->duration; +		arg.dwell_time_active_6g = req->duration; +		arg.dwell_time_passive = req->duration; +		arg.dwell_time_passive_6g = req->duration; +		arg.burst_duration = req->duration; + +		scan_timeout = min_t(u32, arg.max_rest_time * +				(arg.num_chan - 1) + (req->duration + +				ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) * +				arg.num_chan, arg.max_scan_time); +	} else { +		scan_timeout = arg.max_scan_time; +	} + +	/* Add a margin to account for event/command processing */ +	scan_timeout += ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD; +  	ret = ath11k_start_scan(ar, &arg);  	if (ret) {  		ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret); @@ -3689,10 +3713,8 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,  		spin_unlock_bh(&ar->data_lock);  	} -	/* Add a 200ms margin to account for event/command processing */  	ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, -				     msecs_to_jiffies(arg.max_scan_time + -						      ATH11K_MAC_SCAN_TIMEOUT_MSECS)); +				     msecs_to_jiffies(scan_timeout));  exit:  	kfree(arg.chan_list); @@ -4215,10 +4237,11 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)  	const u8 *ht_mcs_mask;  	const u16 *vht_mcs_mask;  	const u16 *he_mcs_mask; -	u32 changed, bw, nss, smps; +	u32 changed, bw, nss, smps, bw_prev;  	int err, num_vht_rates, num_he_rates;  	const struct cfg80211_bitrate_mask *mask;  	struct peer_assoc_params peer_arg; +	enum wmi_phy_mode peer_phymode;  	arsta = container_of(wk, struct ath11k_sta, update_wk);  	sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); @@ -4239,6 +4262,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)  	arsta->changed = 0;  	bw = arsta->bw; +	bw_prev = arsta->bw_prev;  	nss = arsta->nss;  	smps = arsta->smps; @@ -4252,26 +4276,57 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)  			   ath11k_mac_max_he_nss(he_mcs_mask)));  	if (changed & IEEE80211_RC_BW_CHANGED) { -		/* Send peer assoc command before set peer bandwidth param to -		 * avoid the mismatch between the peer phymode and the peer -		 * bandwidth. -		 */ -		ath11k_peer_assoc_prepare(ar, arvif->vif, sta, &peer_arg, true); +		/* Get the peer phymode */ +		ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg); +		peer_phymode = peer_arg.peer_phymode; + +		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n", +			   sta->addr, bw, peer_phymode); + +		if (bw > bw_prev) { +			/* BW is upgraded. In this case we send WMI_PEER_PHYMODE +			 * followed by WMI_PEER_CHWIDTH +			 */ +			ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n", +				   sta->addr, bw, bw_prev); + +			err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, +							WMI_PEER_PHYMODE, peer_phymode); + +			if (err) { +				ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", +					    sta->addr, peer_phymode, err); +				goto err_rc_bw_changed; +			} -		peer_arg.is_assoc = false; -		err = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg); -		if (err) { -			ath11k_warn(ar->ab, "failed to send peer assoc for STA %pM vdev %i: %d\n", -				    sta->addr, arvif->vdev_id, err); -		} else if (wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {  			err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,  							WMI_PEER_CHWIDTH, bw); +  			if (err)  				ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n",  					    sta->addr, bw, err);  		} else { -			ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n", -				    sta->addr, arvif->vdev_id); +			/* BW is downgraded. In this case we send WMI_PEER_CHWIDTH +			 * followed by WMI_PEER_PHYMODE +			 */ +			ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n", +				   sta->addr, bw, bw_prev); + +			err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, +							WMI_PEER_CHWIDTH, bw); + +			if (err) { +				ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", +					    sta->addr, bw, err); +				goto err_rc_bw_changed; +			} + +			err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, +							WMI_PEER_PHYMODE, peer_phymode); + +			if (err) +				ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", +					    sta->addr, peer_phymode, err);  		}  	} @@ -4352,6 +4407,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)  		}  	} +err_rc_bw_changed:  	mutex_unlock(&ar->conf_mutex);  } @@ -4505,6 +4561,34 @@ exit:  	return ret;  } +static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar, +					      struct ieee80211_sta *sta) +{ +	u32 bw = WMI_PEER_CHWIDTH_20MHZ; + +	switch (sta->deflink.bandwidth) { +	case IEEE80211_STA_RX_BW_20: +		bw = WMI_PEER_CHWIDTH_20MHZ; +		break; +	case IEEE80211_STA_RX_BW_40: +		bw = WMI_PEER_CHWIDTH_40MHZ; +		break; +	case IEEE80211_STA_RX_BW_80: +		bw = WMI_PEER_CHWIDTH_80MHZ; +		break; +	case IEEE80211_STA_RX_BW_160: +		bw = WMI_PEER_CHWIDTH_160MHZ; +		break; +	default: +		ath11k_warn(ar->ab, "Invalid bandwidth %d for %pM\n", +			    sta->deflink.bandwidth, sta->addr); +		bw = WMI_PEER_CHWIDTH_20MHZ; +		break; +	} + +	return bw; +} +  static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,  				   struct ieee80211_vif *vif,  				   struct ieee80211_sta *sta, @@ -4590,6 +4674,12 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,  		if (ret)  			ath11k_warn(ar->ab, "Failed to associate station: %pM\n",  				    sta->addr); + +		spin_lock_bh(&ar->data_lock); +		/* Set arsta bw and prev bw */ +		arsta->bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta); +		arsta->bw_prev = arsta->bw; +		spin_unlock_bh(&ar->data_lock);  	} else if (old_state == IEEE80211_STA_ASSOC &&  		   new_state == IEEE80211_STA_AUTHORIZED) {  		spin_lock_bh(&ar->ab->base_lock); @@ -4713,28 +4803,8 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,  	spin_lock_bh(&ar->data_lock);  	if (changed & IEEE80211_RC_BW_CHANGED) { -		bw = WMI_PEER_CHWIDTH_20MHZ; - -		switch (sta->deflink.bandwidth) { -		case IEEE80211_STA_RX_BW_20: -			bw = WMI_PEER_CHWIDTH_20MHZ; -			break; -		case IEEE80211_STA_RX_BW_40: -			bw = WMI_PEER_CHWIDTH_40MHZ; -			break; -		case IEEE80211_STA_RX_BW_80: -			bw = WMI_PEER_CHWIDTH_80MHZ; -			break; -		case IEEE80211_STA_RX_BW_160: -			bw = WMI_PEER_CHWIDTH_160MHZ; -			break; -		default: -			ath11k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n", -				    sta->deflink.bandwidth, sta->addr); -			bw = WMI_PEER_CHWIDTH_20MHZ; -			break; -		} - +		bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta); +		arsta->bw_prev = arsta->bw;  		arsta->bw = bw;  	} @@ -6163,6 +6233,40 @@ void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab)  	}  } +static int ath11k_mac_vdev_delete(struct ath11k *ar, struct ath11k_vif *arvif) +{ +	unsigned long time_left; +	struct ieee80211_vif *vif = arvif->vif; +	int ret = 0; + +	lockdep_assert_held(&ar->conf_mutex); + +	reinit_completion(&ar->vdev_delete_done); + +	ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); +	if (ret) { +		ath11k_warn(ar->ab, "failed to delete WMI vdev %d: %d\n", +			    arvif->vdev_id, ret); +		return ret; +	} + +	time_left = wait_for_completion_timeout(&ar->vdev_delete_done, +						ATH11K_VDEV_DELETE_TIMEOUT_HZ); +	if (time_left == 0) { +		ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n"); +		return -ETIMEDOUT; +	} + +	ar->ab->free_vdev_map |= 1LL << (arvif->vdev_id); +	ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); +	ar->num_created_vdevs--; + +	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", +		   vif->addr, arvif->vdev_id); + +	return ret; +} +  static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,  				       struct ieee80211_vif *vif)  { @@ -6373,18 +6477,16 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,  	ath11k_dp_vdev_tx_attach(ar, arvif); +	ath11k_debugfs_add_interface(arvif); +  	if (vif->type != NL80211_IFTYPE_MONITOR &&  	    test_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags)) {  		ret = ath11k_mac_monitor_vdev_create(ar); -		if (ret) { +		if (ret)  			ath11k_warn(ar->ab, "failed to create monitor vdev during add interface: %d",  				    ret); -			goto err_peer_del; -		}  	} -	ath11k_debugfs_add_interface(arvif); -  	mutex_unlock(&ar->conf_mutex);  	return 0; @@ -6400,16 +6502,12 @@ err_peer_del:  	}  err_vdev_del: -	ath11k_wmi_vdev_delete(ar, arvif->vdev_id); -	ar->num_created_vdevs--; -	ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); -	ab->free_vdev_map |= 1LL << arvif->vdev_id; +	ath11k_mac_vdev_delete(ar, arvif);  	spin_lock_bh(&ar->data_lock);  	list_del(&arvif->list);  	spin_unlock_bh(&ar->data_lock);  err: -	ath11k_debugfs_remove_interface(arvif);  	mutex_unlock(&ar->conf_mutex);  	return ret; @@ -6432,7 +6530,6 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,  	struct ath11k *ar = hw->priv;  	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);  	struct ath11k_base *ab = ar->ab; -	unsigned long time_left;  	int ret;  	int i; @@ -6453,29 +6550,13 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,  				    arvif->vdev_id, ret);  	} -	reinit_completion(&ar->vdev_delete_done); - -	ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); +	ret = ath11k_mac_vdev_delete(ar, arvif);  	if (ret) { -		ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n", +		ath11k_warn(ab, "failed to delete vdev %d: %d\n",  			    arvif->vdev_id, ret);  		goto err_vdev_del;  	} -	time_left = wait_for_completion_timeout(&ar->vdev_delete_done, -						ATH11K_VDEV_DELETE_TIMEOUT_HZ); -	if (time_left == 0) { -		ath11k_warn(ab, "Timeout in receiving vdev delete response\n"); -		goto err_vdev_del; -	} - -	ab->free_vdev_map |= 1LL << (arvif->vdev_id); -	ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); -	ar->num_created_vdevs--; - -	ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", -		   vif->addr, arvif->vdev_id); -  	if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {  		clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);  		ar->monitor_vdev_id = -1; @@ -9015,6 +9096,9 @@ static int __ath11k_mac_register(struct ath11k *ar)  				      NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);  	} +	wiphy_ext_feature_set(ar->hw->wiphy, +			      NL80211_EXT_FEATURE_SET_SCAN_DWELL); +  	ath11k_reg_init(ar);  	if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { diff --git a/drivers/net/wireless/ath/ath11k/pcic.c b/drivers/net/wireless/ath/ath11k/pcic.c index 380f9d37b644..30d66147223f 100644 --- a/drivers/net/wireless/ath/ath11k/pcic.c +++ b/drivers/net/wireless/ath/ath11k/pcic.c @@ -218,9 +218,16 @@ int ath11k_pcic_read(struct ath11k_base *ab, void *buf, u32 start, u32 end)  	if (wakeup_required && ab->pci.ops->wakeup) {  		ret = ab->pci.ops->wakeup(ab);  		if (ret) { -			ath11k_warn(ab, "failed to wakeup for read from 0x%x: %d\n", -				    start, ret); -			return ret; +			ath11k_warn(ab, +				    "wakeup failed, data may be invalid: %d", +				    ret); +			/* Even though wakeup() failed, continue processing rather +			 * than returning because some parts of the data may still +			 * be valid and useful in some cases, e.g. could give us +			 * some clues on firmware crash. +			 * Mislead due to invalid data could be avoided because we +			 * are aware of the wakeup failure. +			 */  		}  	} diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index 51de2208b789..145f20a681bd 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -19,6 +19,7 @@  #define SLEEP_CLOCK_SELECT_INTERNAL_BIT	0x02  #define HOST_CSTATE_BIT			0x04  #define PLATFORM_CAP_PCIE_GLOBAL_RESET	0x08 +#define PLATFORM_CAP_PCIE_PME_D3COLD	0x10  #define FW_BUILD_ID_MASK "QC_IMAGE_VERSION_STRING=" @@ -1752,6 +1753,8 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)  	if (ab->hw_params.global_reset)  		req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET; +	req.nm_modem |= PLATFORM_CAP_PCIE_PME_D3COLD; +  	ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi host cap request\n");  	ret = qmi_txn_init(&ab->qmi.handle, &txn, @@ -1961,7 +1964,7 @@ static void ath11k_qmi_free_target_mem_chunk(struct ath11k_base *ab)  			continue;  		dma_free_coherent(ab->dev, -				  ab->qmi.target_mem[i].size, +				  ab->qmi.target_mem[i].prev_size,  				  ab->qmi.target_mem[i].vaddr,  				  ab->qmi.target_mem[i].paddr);  		ab->qmi.target_mem[i].vaddr = NULL; @@ -1982,12 +1985,12 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)  		 * in such case, no need to allocate memory for FW again.  		 */  		if (chunk->vaddr) { -			if (chunk->prev_type == chunk->type || +			if (chunk->prev_type == chunk->type &&  			    chunk->prev_size == chunk->size)  				continue;  			/* cannot reuse the existing chunk */ -			dma_free_coherent(ab->dev, chunk->size, +			dma_free_coherent(ab->dev, chunk->prev_size,  					  chunk->vaddr, chunk->paddr);  			chunk->vaddr = NULL;  		} @@ -3158,6 +3161,9 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)  		case ATH11K_QMI_EVENT_SERVER_EXIT:  			set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);  			set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); + +			if (!ab->is_reset) +				ath11k_core_pre_reconfigure_recovery(ab);  			break;  		case ATH11K_QMI_EVENT_REQUEST_MEM:  			ret = ath11k_qmi_event_mem_request(qmi); diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c index 7ee3ff69dfc8..6fae4e61ede7 100644 --- a/drivers/net/wireless/ath/ath11k/reg.c +++ b/drivers/net/wireless/ath/ath11k/reg.c @@ -287,11 +287,7 @@ int ath11k_regd_update(struct ath11k *ar)  		goto err;  	} -	rtnl_lock(); -	wiphy_lock(ar->hw->wiphy); -	ret = regulatory_set_wiphy_regd_sync(ar->hw->wiphy, regd_copy); -	wiphy_unlock(ar->hw->wiphy); -	rtnl_unlock(); +	ret = regulatory_set_wiphy_regd(ar->hw->wiphy, regd_copy);  	kfree(regd_copy); diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index fad9f8d308a2..2a8a3e3dcff6 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -6829,7 +6829,7 @@ static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab,  	}  	ath11k_dbg(ab, ATH11K_DBG_WMI, -		   "peer sta ps chnange ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n", +		   "peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",  		   ev->peer_macaddr.addr, ev->peer_ps_state,  		   ev->ps_supported_bitmap, ev->peer_ps_valid,  		   ev->peer_ps_timestamp); diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 9bdfcee2f448..eff94bcd1f0a 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -45,11 +45,6 @@ ath9k_hw-y:=	\  		ar9003_eeprom.o \  		ar9003_paprd.o -# FIXME: temporarily silence -Warray-bounds on non W=1+ builds -ifndef KBUILD_EXTRA_WARN -CFLAGS_mac.o += -Wno-array-bounds -endif -  ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o  ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 4d9002a9d082..1a2e0c7eeb02 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -708,14 +708,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)  	struct rx_buf *rx_buf = (struct rx_buf *)urb->context;  	struct hif_device_usb *hif_dev = rx_buf->hif_dev;  	struct sk_buff *skb = rx_buf->skb; -	struct sk_buff *nskb;  	int ret;  	if (!skb)  		return;  	if (!hif_dev) -		goto free; +		goto free_skb;  	switch (urb->status) {  	case 0: @@ -724,7 +723,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)  	case -ECONNRESET:  	case -ENODEV:  	case -ESHUTDOWN: -		goto free; +		goto free_skb;  	default:  		skb_reset_tail_pointer(skb);  		skb_trim(skb, 0); @@ -735,25 +734,27 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)  	if (likely(urb->actual_length != 0)) {  		skb_put(skb, urb->actual_length); -		/* Process the command first */ +		/* +		 * Process the command first. +		 * skb is either freed here or passed to be +		 * managed to another callback function. +		 */  		ath9k_htc_rx_msg(hif_dev->htc_handle, skb,  				 skb->len, USB_REG_IN_PIPE); - -		nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); -		if (!nskb) { +		skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); +		if (!skb) {  			dev_err(&hif_dev->udev->dev,  				"ath9k_htc: REG_IN memory allocation failure\n"); -			urb->context = NULL; -			return; +			goto free_rx_buf;  		} -		rx_buf->skb = nskb; +		rx_buf->skb = skb;  		usb_fill_int_urb(urb, hif_dev->udev,  				 usb_rcvintpipe(hif_dev->udev,  						 USB_REG_IN_PIPE), -				 nskb->data, MAX_REG_IN_BUF_SIZE, +				 skb->data, MAX_REG_IN_BUF_SIZE,  				 ath9k_hif_usb_reg_in_cb, rx_buf, 1);  	} @@ -762,12 +763,13 @@ resubmit:  	ret = usb_submit_urb(urb, GFP_ATOMIC);  	if (ret) {  		usb_unanchor_urb(urb); -		goto free; +		goto free_skb;  	}  	return; -free: +free_skb:  	kfree_skb(skb); +free_rx_buf:  	kfree(rx_buf);  	urb->context = NULL;  } @@ -780,14 +782,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)  	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);  	list_for_each_entry_safe(tx_buf, tx_buf_tmp,  				 &hif_dev->tx.tx_buf, list) { -		usb_get_urb(tx_buf->urb); -		spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); -		usb_kill_urb(tx_buf->urb);  		list_del(&tx_buf->list);  		usb_free_urb(tx_buf->urb);  		kfree(tx_buf->buf);  		kfree(tx_buf); -		spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);  	}  	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); @@ -1329,10 +1327,24 @@ static int send_eject_command(struct usb_interface *interface)  static int ath9k_hif_usb_probe(struct usb_interface *interface,  			       const struct usb_device_id *id)  { +	struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in, *int_out;  	struct usb_device *udev = interface_to_usbdev(interface); +	struct usb_host_interface *alt;  	struct hif_device_usb *hif_dev;  	int ret = 0; +	/* Verify the expected endpoints are present */ +	alt = interface->cur_altsetting; +	if (usb_find_common_endpoints(alt, &bulk_in, &bulk_out, &int_in, &int_out) < 0 || +	    usb_endpoint_num(bulk_in) != USB_WLAN_RX_PIPE || +	    usb_endpoint_num(bulk_out) != USB_WLAN_TX_PIPE || +	    usb_endpoint_num(int_in) != USB_REG_IN_PIPE || +	    usb_endpoint_num(int_out) != USB_REG_OUT_PIPE) { +		dev_err(&udev->dev, +			"ath9k_htc: Device endpoint numbers are not the expected ones\n"); +		return -ENODEV; +	} +  	if (id->driver_info == STORAGE_DEVICE)  		return send_eject_command(interface); diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 039bf0c35fbe..3363fc4e8966 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c @@ -266,7 +266,9 @@ static void ath_mci_set_concur_txprio(struct ath_softc *sc)  			stomp_txprio[ATH_BTCOEX_STOMP_NONE] =  				ATH_MCI_INQUIRY_PRIO;  	} else { -		u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */ +		static const u8 prof_prio[] = { +			50, 90, 94, 52 +		}; /* RFCOMM, A2DP, HID, PAN */  		stomp_txprio[ATH_BTCOEX_STOMP_LOW] =  		stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff; @@ -644,7 +646,9 @@ void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all)  	struct ath_hw *ah = sc->sc_ah;  	struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;  	struct ath9k_channel *chan = ah->curchan; -	u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff}; +	static const u32 channelmap[] = { +		0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff +	};  	int i;  	s16 chan_start, chan_end;  	u16 wlan_chan; diff --git a/drivers/net/wireless/ath/carl9170/Makefile b/drivers/net/wireless/ath/carl9170/Makefile index 7463baa62fa8..1a81868ce26d 100644 --- a/drivers/net/wireless/ath/carl9170/Makefile +++ b/drivers/net/wireless/ath/carl9170/Makefile @@ -3,8 +3,3 @@ carl9170-objs := main.o usb.o cmd.o mac.o phy.o led.o fw.o tx.o rx.o  carl9170-$(CONFIG_CARL9170_DEBUGFS) += debug.o  obj-$(CONFIG_CARL9170) += carl9170.o - -# FIXME: temporarily silence -Warray-bounds on non W=1+ builds -ifndef KBUILD_EXTRA_WARN -CFLAGS_cmd.o += -Wno-array-bounds -endif diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h index 0a4e42e806b9..ded2c6d0a759 100644 --- a/drivers/net/wireless/ath/carl9170/wlan.h +++ b/drivers/net/wireless/ath/carl9170/wlan.h @@ -271,7 +271,7 @@ struct ar9170_tx_frame {  	union {  		struct ieee80211_hdr i3e; -		u8 payload[0]; +		DECLARE_FLEX_ARRAY(u8, payload);  	} data;  } __packed; diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 04d1aa0e2d35..c021ebcddee7 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -2154,7 +2154,7 @@ static const struct file_operations fops_led_blink_time = {  };  /*---------FW capabilities------------*/ -static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data) +static int fw_capabilities_show(struct seq_file *s, void *data)  {  	struct wil6210_priv *wil = s->private; @@ -2163,22 +2163,10 @@ static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data)  	return 0;  } - -static int wil_fw_capabilities_seq_open(struct inode *inode, struct file *file) -{ -	return single_open(file, wil_fw_capabilities_debugfs_show, -			   inode->i_private); -} - -static const struct file_operations fops_fw_capabilities = { -	.open		= wil_fw_capabilities_seq_open, -	.release	= single_release, -	.read		= seq_read, -	.llseek		= seq_lseek, -}; +DEFINE_SHOW_ATTRIBUTE(fw_capabilities);  /*---------FW version------------*/ -static int wil_fw_version_debugfs_show(struct seq_file *s, void *data) +static int fw_version_show(struct seq_file *s, void *data)  {  	struct wil6210_priv *wil = s->private; @@ -2189,19 +2177,7 @@ static int wil_fw_version_debugfs_show(struct seq_file *s, void *data)  	return 0;  } - -static int wil_fw_version_seq_open(struct inode *inode, struct file *file) -{ -	return single_open(file, wil_fw_version_debugfs_show, -			   inode->i_private); -} - -static const struct file_operations fops_fw_version = { -	.open		= wil_fw_version_seq_open, -	.release	= single_release, -	.read		= seq_read, -	.llseek		= seq_lseek, -}; +DEFINE_SHOW_ATTRIBUTE(fw_version);  /*---------suspend_stats---------*/  static ssize_t wil_write_suspend_stats(struct file *file, @@ -2366,8 +2342,8 @@ static const struct {  	{"recovery", 0644,		&fops_recovery},  	{"led_cfg",	0644,		&fops_led_cfg},  	{"led_blink_time",	0644,	&fops_led_blink_time}, -	{"fw_capabilities",	0444,	&fops_fw_capabilities}, -	{"fw_version",	0444,		&fops_fw_version}, +	{"fw_capabilities",	0444,	&fw_capabilities_fops}, +	{"fw_version",	0444,		&fw_version_fops},  	{"suspend_stats",	0644,	&fops_suspend_stats},  	{"compressed_rx_status", 0644,	&fops_compressed_rx_status},  	{"srings",	0444,		&srings_fops}, | 
