diff options
Diffstat (limited to 'drivers/net/wireless')
25 files changed, 161 insertions, 62 deletions
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index dfb26f03c1a2..1b05b5d7a038 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -1113,7 +1113,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,  		if (!avp->assoc)  			return false; -		skb = ieee80211_nullfunc_get(sc->hw, vif); +		skb = ieee80211_nullfunc_get(sc->hw, vif, false);  		if (!skb)  			return false; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index f7d228b5ba93..987f1252a3cf 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -384,6 +384,18 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)  		}  	} +	if (changed & IEEE80211_CONF_CHANGE_PS) { +		list_for_each_entry(tmp, &wcn->vif_list, list) { +			vif = wcn36xx_priv_to_vif(tmp); +			if (hw->conf.flags & IEEE80211_CONF_PS) { +				if (vif->bss_conf.ps) /* ps allowed ? */ +					wcn36xx_pmc_enter_bmps_state(wcn, vif); +			} else { +				wcn36xx_pmc_exit_bmps_state(wcn, vif); +			} +		} +	} +  	mutex_unlock(&wcn->conf_mutex);  	return 0; @@ -747,17 +759,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,  		vif_priv->dtim_period = bss_conf->dtim_period;  	} -	if (changed & BSS_CHANGED_PS) { -		wcn36xx_dbg(WCN36XX_DBG_MAC, -			    "mac bss PS set %d\n", -			    bss_conf->ps); -		if (bss_conf->ps) { -			wcn36xx_pmc_enter_bmps_state(wcn, vif); -		} else { -			wcn36xx_pmc_exit_bmps_state(wcn, vif); -		} -	} -  	if (changed & BSS_CHANGED_BSSID) {  		wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",  			    bss_conf->bssid); diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c index 589fe5f70971..1976b80c235f 100644 --- a/drivers/net/wireless/ath/wcn36xx/pmc.c +++ b/drivers/net/wireless/ath/wcn36xx/pmc.c @@ -45,8 +45,10 @@ int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn,  	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);  	if (WCN36XX_BMPS != vif_priv->pw_state) { -		wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n"); -		return -EINVAL; +		/* Unbalanced call or last BMPS enter failed */ +		wcn36xx_dbg(WCN36XX_DBG_PMC, +			    "Not in BMPS mode, no need to exit\n"); +		return -EALREADY;  	}  	wcn36xx_smd_exit_bmps(wcn, vif);  	vif_priv->pw_state = WCN36XX_FULL_POWER; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 310c4e2746aa..cdf9e4161592 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -2070,7 +2070,7 @@ static int brcmf_sdio_txpkt_hdalign(struct brcmf_sdio *bus, struct sk_buff *pkt)  	return head_pad;  } -/** +/*   * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for   * bus layer usage.   */ @@ -4121,8 +4121,8 @@ release:  	sdio_release_host(sdiodev->func[1]);  fail:  	brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err); -	device_release_driver(dev);  	device_release_driver(&sdiodev->func[2]->dev); +	device_release_driver(dev);  }  struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h b/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h index 87b4434224a1..dfa111bb411e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h @@ -68,6 +68,9 @@   * @IWL_MVM_DQA_CMD_QUEUE: a queue reserved for sending HCMDs to the FW   * @IWL_MVM_DQA_AUX_QUEUE: a queue reserved for aux frames   * @IWL_MVM_DQA_P2P_DEVICE_QUEUE: a queue reserved for P2P device frames + * @IWL_MVM_DQA_INJECT_MONITOR_QUEUE: a queue reserved for injection using + *	monitor mode. Note this queue is the same as the queue for P2P device + *	but we can't have active monitor mode along with P2P device anyway.   * @IWL_MVM_DQA_GCAST_QUEUE: a queue reserved for P2P GO/SoftAP GCAST frames   * @IWL_MVM_DQA_BSS_CLIENT_QUEUE: a queue reserved for BSS activity, to ensure   *	that we are never left without the possibility to connect to an AP. @@ -87,6 +90,7 @@ enum iwl_mvm_dqa_txq {  	IWL_MVM_DQA_CMD_QUEUE = 0,  	IWL_MVM_DQA_AUX_QUEUE = 1,  	IWL_MVM_DQA_P2P_DEVICE_QUEUE = 2, +	IWL_MVM_DQA_INJECT_MONITOR_QUEUE = 2,  	IWL_MVM_DQA_GCAST_QUEUE = 3,  	IWL_MVM_DQA_BSS_CLIENT_QUEUE = 4,  	IWL_MVM_DQA_MIN_MGMT_QUEUE = 5, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 9c889a32fe24..223fb77a3aa9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -209,8 +209,6 @@ static inline void iwl_fw_dbg_stop_recording(struct iwl_fw_runtime *fwrt)  static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt)  { -	iwl_fw_dbg_stop_recording(fwrt); -  	fwrt->dump.conf = FW_DBG_INVALID;  } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index ca0b5536a8a6..921cab9e2d73 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -117,6 +117,7 @@  #define FH_RSCSR_FRAME_INVALID		0x55550000  #define FH_RSCSR_FRAME_ALIGN		0x40  #define FH_RSCSR_RPA_EN			BIT(25) +#define FH_RSCSR_RADA_EN		BIT(26)  #define FH_RSCSR_RXQ_POS		16  #define FH_RSCSR_RXQ_MASK		0x3F0000 @@ -128,7 +129,8 @@ struct iwl_rx_packet {  	 * 31:    flag flush RB request  	 * 30:    flag ignore TC (terminal counter) request  	 * 29:    flag fast IRQ request -	 * 28-26: Reserved +	 * 28-27: Reserved +	 * 26:    RADA enabled  	 * 25:    Offload enabled  	 * 24:    RPF enabled  	 * 23:    RSS enabled diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index a2bf530eeae4..2f22e14e00fe 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -787,7 +787,7 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,  					 u32 action)  {  	struct iwl_mac_ctx_cmd cmd = {}; -	u32 tfd_queue_msk = 0; +	u32 tfd_queue_msk = BIT(mvm->snif_queue);  	int ret;  	WARN_ON(vif->type != NL80211_IFTYPE_MONITOR); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 4575595ab022..55ab5349dd40 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -972,6 +972,7 @@ struct iwl_mvm {  	/* Tx queues */  	u16 aux_queue; +	u16 snif_queue;  	u16 probe_queue;  	u16 p2p_dev_queue; @@ -1060,6 +1061,7 @@ struct iwl_mvm {   * @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running   * @IWL_MVM_STATUS_D3_RECONFIG: D3 reconfiguration is being done   * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running + * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA   */  enum iwl_mvm_status {  	IWL_MVM_STATUS_HW_RFKILL, @@ -1071,6 +1073,7 @@ enum iwl_mvm_status {  	IWL_MVM_STATUS_ROC_AUX_RUNNING,  	IWL_MVM_STATUS_D3_RECONFIG,  	IWL_MVM_STATUS_FIRMWARE_RUNNING, +	IWL_MVM_STATUS_NEED_FLUSH_P2P,  };  /* Keep track of completed init configuration */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 7078b7e458be..45470b6b351a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -624,6 +624,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,  	mvm->fw_restart = iwlwifi_mod_params.fw_restart ? -1 : 0;  	mvm->aux_queue = IWL_MVM_DQA_AUX_QUEUE; +	mvm->snif_queue = IWL_MVM_DQA_INJECT_MONITOR_QUEUE;  	mvm->probe_queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;  	mvm->p2p_dev_queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 76dc58381e1c..3b8d44361380 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -213,6 +213,7 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,  					struct ieee80211_rx_status *rx_status)  {  	int energy_a, energy_b, max_energy; +	u32 rate_flags = le32_to_cpu(desc->rate_n_flags);  	energy_a = desc->energy_a;  	energy_a = energy_a ? -energy_a : S8_MIN; @@ -224,7 +225,8 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,  			energy_a, energy_b, max_energy);  	rx_status->signal = max_energy; -	rx_status->chains = 0; /* TODO: phy info */ +	rx_status->chains = +		(rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;  	rx_status->chain_signal[0] = energy_a;  	rx_status->chain_signal[1] = energy_b;  	rx_status->chain_signal[2] = S8_MIN; @@ -232,8 +234,8 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,  static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,  			     struct ieee80211_rx_status *stats, -			     struct iwl_rx_mpdu_desc *desc, int queue, -			     u8 *crypt_len) +			     struct iwl_rx_mpdu_desc *desc, u32 pkt_flags, +			     int queue, u8 *crypt_len)  {  	u16 status = le16_to_cpu(desc->status); @@ -253,6 +255,8 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,  			return -1;  		stats->flag |= RX_FLAG_DECRYPTED; +		if (pkt_flags & FH_RSCSR_RADA_EN) +			stats->flag |= RX_FLAG_MIC_STRIPPED;  		*crypt_len = IEEE80211_CCMP_HDR_LEN;  		return 0;  	case IWL_RX_MPDU_STATUS_SEC_TKIP: @@ -270,6 +274,10 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,  		if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) ==  				IWL_RX_MPDU_STATUS_SEC_WEP)  			*crypt_len = IEEE80211_WEP_IV_LEN; + +		if (pkt_flags & FH_RSCSR_RADA_EN) +			stats->flag |= RX_FLAG_ICV_STRIPPED; +  		return 0;  	case IWL_RX_MPDU_STATUS_SEC_EXT_ENC:  		if (!(status & IWL_RX_MPDU_STATUS_MIC_OK)) @@ -848,7 +856,9 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,  	rx_status = IEEE80211_SKB_RXCB(skb); -	if (iwl_mvm_rx_crypto(mvm, hdr, rx_status, desc, queue, &crypt_len)) { +	if (iwl_mvm_rx_crypto(mvm, hdr, rx_status, desc, +			      le32_to_cpu(pkt->len_n_flags), queue, +			      &crypt_len)) {  		kfree_skb(skb);  		return;  	} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index c19f98489d4e..1add5615fc3a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1709,29 +1709,29 @@ void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta)  	sta->sta_id = IWL_MVM_INVALID_STA;  } -static void iwl_mvm_enable_aux_queue(struct iwl_mvm *mvm) +static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue, +					  u8 sta_id, u8 fifo)  {  	unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?  					mvm->cfg->base_params->wd_timeout :  					IWL_WATCHDOG_DISABLED;  	if (iwl_mvm_has_new_tx_api(mvm)) { -		int queue = iwl_mvm_tvqm_enable_txq(mvm, mvm->aux_queue, -						    mvm->aux_sta.sta_id, -						    IWL_MAX_TID_COUNT, -						    wdg_timeout); -		mvm->aux_queue = queue; +		int tvqm_queue = +			iwl_mvm_tvqm_enable_txq(mvm, *queue, sta_id, +						IWL_MAX_TID_COUNT, +						wdg_timeout); +		*queue = tvqm_queue;  	} else {  		struct iwl_trans_txq_scd_cfg cfg = { -			.fifo = IWL_MVM_TX_FIFO_MCAST, -			.sta_id = mvm->aux_sta.sta_id, +			.fifo = fifo, +			.sta_id = sta_id,  			.tid = IWL_MAX_TID_COUNT,  			.aggregate = false,  			.frame_limit = IWL_FRAME_LIMIT,  		}; -		iwl_mvm_enable_txq(mvm, mvm->aux_queue, mvm->aux_queue, 0, &cfg, -				   wdg_timeout); +		iwl_mvm_enable_txq(mvm, *queue, *queue, 0, &cfg, wdg_timeout);  	}  } @@ -1750,7 +1750,9 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)  	/* Map Aux queue to fifo - needs to happen before adding Aux station */  	if (!iwl_mvm_has_new_tx_api(mvm)) -		iwl_mvm_enable_aux_queue(mvm); +		iwl_mvm_enable_aux_snif_queue(mvm, &mvm->aux_queue, +					      mvm->aux_sta.sta_id, +					      IWL_MVM_TX_FIFO_MCAST);  	ret = iwl_mvm_add_int_sta_common(mvm, &mvm->aux_sta, NULL,  					 MAC_INDEX_AUX, 0); @@ -1764,7 +1766,9 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)  	 * to firmware so enable queue here - after the station was added  	 */  	if (iwl_mvm_has_new_tx_api(mvm)) -		iwl_mvm_enable_aux_queue(mvm); +		iwl_mvm_enable_aux_snif_queue(mvm, &mvm->aux_queue, +					      mvm->aux_sta.sta_id, +					      IWL_MVM_TX_FIFO_MCAST);  	return 0;  } @@ -1772,10 +1776,31 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)  int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +	int ret;  	lockdep_assert_held(&mvm->mutex); -	return iwl_mvm_add_int_sta_common(mvm, &mvm->snif_sta, vif->addr, + +	/* Map snif queue to fifo - must happen before adding snif station */ +	if (!iwl_mvm_has_new_tx_api(mvm)) +		iwl_mvm_enable_aux_snif_queue(mvm, &mvm->snif_queue, +					      mvm->snif_sta.sta_id, +					      IWL_MVM_TX_FIFO_BE); + +	ret = iwl_mvm_add_int_sta_common(mvm, &mvm->snif_sta, vif->addr,  					 mvmvif->id, 0); +	if (ret) +		return ret; + +	/* +	 * For 22000 firmware and on we cannot add queue to a station unknown +	 * to firmware so enable queue here - after the station was added +	 */ +	if (iwl_mvm_has_new_tx_api(mvm)) +		iwl_mvm_enable_aux_snif_queue(mvm, &mvm->snif_queue, +					      mvm->snif_sta.sta_id, +					      IWL_MVM_TX_FIFO_BE); + +	return 0;  }  int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) @@ -1784,6 +1809,8 @@ int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	lockdep_assert_held(&mvm->mutex); +	iwl_mvm_disable_txq(mvm, mvm->snif_queue, mvm->snif_queue, +			    IWL_MAX_TID_COUNT, 0);  	ret = iwl_mvm_rm_sta_common(mvm, mvm->snif_sta.sta_id);  	if (ret)  		IWL_WARN(mvm, "Failed sending remove station\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 4d0314912e94..e25cda9fbf6c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -132,6 +132,24 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)  	 * executed, and a new time event means a new command.  	 */  	iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true, CMD_ASYNC); + +	/* Do the same for the P2P device queue (STA) */ +	if (test_and_clear_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status)) { +		struct iwl_mvm_vif *mvmvif; + +		/* +		 * NB: access to this pointer would be racy, but the flush bit +		 * can only be set when we had a P2P-Device VIF, and we have a +		 * flush of this work in iwl_mvm_prepare_mac_removal() so it's +		 * not really racy. +		 */ + +		if (!WARN_ON(!mvm->p2p_device_vif)) { +			mvmvif = iwl_mvm_vif_from_mac80211(mvm->p2p_device_vif); +			iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true, +					  CMD_ASYNC); +		} +	}  }  static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) @@ -855,10 +873,12 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm)  	mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif); -	if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) +	if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {  		iwl_mvm_remove_time_event(mvm, mvmvif, te_data); -	else +		set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); +	} else {  		iwl_mvm_remove_aux_roc_te(mvm, mvmvif, te_data); +	}  	iwl_mvm_roc_finished(mvm);  } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 593b7f97b29c..333bcb75b8af 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -657,7 +657,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)  			if (ap_sta_id != IWL_MVM_INVALID_STA)  				sta_id = ap_sta_id;  		} else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) { -			queue = mvm->aux_queue; +			queue = mvm->snif_queue; +			sta_id = mvm->snif_sta.sta_id;  		}  	} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index d46115e2d69e..03ffd84786ca 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -1134,9 +1134,18 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,  	unsigned int default_timeout =  		cmd_q ? IWL_DEF_WD_TIMEOUT : mvm->cfg->base_params->wd_timeout; -	if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS)) +	if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS)) { +		/* +		 * We can't know when the station is asleep or awake, so we +		 * must disable the queue hang detection. +		 */ +		if (fw_has_capa(&mvm->fw->ucode_capa, +				IWL_UCODE_TLV_CAPA_STA_PM_NOTIF) && +		    vif && vif->type == NL80211_IFTYPE_AP) +			return IWL_WATCHDOG_DISABLED;  		return iwlmvm_mod_params.tfd_q_hang_detect ?  			default_timeout : IWL_WATCHDOG_DISABLED; +	}  	trigger = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS);  	txq_timer = (void *)trigger->data; @@ -1163,6 +1172,8 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,  		return le32_to_cpu(txq_timer->p2p_go);  	case NL80211_IFTYPE_P2P_DEVICE:  		return le32_to_cpu(txq_timer->p2p_device); +	case NL80211_IFTYPE_MONITOR: +		return default_timeout;  	default:  		WARN_ON(1);  		return mvm->cfg->base_params->wd_timeout; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index f21fe59faccf..ccd7c33c4c28 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -553,6 +553,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {  	{IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)},  	{IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)},  	{IWL_PCI_DEVICE(0x271B, 0x0214, iwl9260_2ac_cfg)}, +	{IWL_PCI_DEVICE(0x271C, 0x0214, iwl9260_2ac_cfg)},  	{IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_cfg)},  	{IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_cfg)},  	{IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_cfg)}, @@ -664,6 +665,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {  	{IWL_PCI_DEVICE(0x2720, 0x0310, iwla000_2ac_cfg_hr_cdb)},  	{IWL_PCI_DEVICE(0x40C0, 0x0000, iwla000_2ax_cfg_hr)},  	{IWL_PCI_DEVICE(0x40C0, 0x0A10, iwla000_2ax_cfg_hr)}, +	{IWL_PCI_DEVICE(0xA0F0, 0x0000, iwla000_2ax_cfg_hr)},  #endif /* CONFIG_IWLMVM */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index d749abeca3ae..403e65c309d0 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -670,11 +670,15 @@ static inline u8 iwl_pcie_get_cmd_index(struct iwl_txq *q, u32 index)  	return index & (q->n_window - 1);  } -static inline void *iwl_pcie_get_tfd(struct iwl_trans_pcie *trans_pcie, +static inline void *iwl_pcie_get_tfd(struct iwl_trans *trans,  				     struct iwl_txq *txq, int idx)  { -	return txq->tfds + trans_pcie->tfd_size * iwl_pcie_get_cmd_index(txq, -									 idx); +	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + +	if (trans->cfg->use_tfh) +		idx = iwl_pcie_get_cmd_index(txq, idx); + +	return txq->tfds + trans_pcie->tfd_size * idx;  }  static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index c59f4581e972..ac05fd1e74c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -49,6 +49,7 @@   *   *****************************************************************************/  #include "iwl-trans.h" +#include "iwl-prph.h"  #include "iwl-context-info.h"  #include "internal.h" @@ -156,6 +157,11 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)  	trans_pcie->is_down = true; +	/* Stop dbgc before stopping device */ +	iwl_write_prph(trans, DBGC_IN_SAMPLE, 0); +	udelay(100); +	iwl_write_prph(trans, DBGC_OUT_CTRL, 0); +  	/* tell the device to stop sending interrupts */  	iwl_disable_interrupts(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index b7a51603465b..4541c86881d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -166,6 +166,7 @@ static void iwl_trans_pcie_dump_regs(struct iwl_trans *trans)  		print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32,  			       4, buf, i, 0);  	} +	goto out;  err_read:  	print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); @@ -1226,6 +1227,15 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)  	trans_pcie->is_down = true; +	/* Stop dbgc before stopping device */ +	if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { +		iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100); +	} else { +		iwl_write_prph(trans, DBGC_IN_SAMPLE, 0); +		udelay(100); +		iwl_write_prph(trans, DBGC_OUT_CTRL, 0); +	} +  	/* tell the device to stop sending interrupts */  	iwl_disable_interrupts(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 16b345f54ff0..6d0a907d5ba5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -171,8 +171,6 @@ static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans,  static void iwl_pcie_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)  { -	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); -  	/* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and  	 * idx is bounded by n_window  	 */ @@ -181,7 +179,7 @@ static void iwl_pcie_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)  	lockdep_assert_held(&txq->lock);  	iwl_pcie_gen2_tfd_unmap(trans, &txq->entries[idx].meta, -				iwl_pcie_get_tfd(trans_pcie, txq, idx)); +				iwl_pcie_get_tfd(trans, txq, idx));  	/* free SKB */  	if (txq->entries) { @@ -364,11 +362,9 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,  					    struct sk_buff *skb,  					    struct iwl_cmd_meta *out_meta)  { -	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;  	int idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr); -	struct iwl_tfh_tfd *tfd = -		iwl_pcie_get_tfd(trans_pcie, txq, idx); +	struct iwl_tfh_tfd *tfd = iwl_pcie_get_tfd(trans, txq, idx);  	dma_addr_t tb_phys;  	bool amsdu;  	int i, len, tb1_len, tb2_len, hdr_len; @@ -565,8 +561,7 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,  	u8 group_id = iwl_cmd_groupid(cmd->id);  	const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];  	u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; -	struct iwl_tfh_tfd *tfd = -		iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr); +	struct iwl_tfh_tfd *tfd = iwl_pcie_get_tfd(trans, txq, txq->write_ptr);  	memset(tfd, 0, sizeof(*tfd)); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index fed6d842a5e1..3f85713c41dc 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -373,7 +373,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,  {  	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);  	int i, num_tbs; -	void *tfd = iwl_pcie_get_tfd(trans_pcie, txq, index); +	void *tfd = iwl_pcie_get_tfd(trans, txq, index);  	/* Sanity check on number of chunks */  	num_tbs = iwl_pcie_tfd_get_num_tbs(trans, tfd); @@ -2018,7 +2018,7 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb,  	}  	trace_iwlwifi_dev_tx(trans->dev, skb, -			     iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr), +			     iwl_pcie_get_tfd(trans, txq, txq->write_ptr),  			     trans_pcie->tfd_size,  			     &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len,  			     hdr_len); @@ -2092,7 +2092,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,  		IEEE80211_CCMP_HDR_LEN : 0;  	trace_iwlwifi_dev_tx(trans->dev, skb, -			     iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr), +			     iwl_pcie_get_tfd(trans, txq, txq->write_ptr),  			     trans_pcie->tfd_size,  			     &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len, 0); @@ -2425,7 +2425,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,  	memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,  	       IWL_FIRST_TB_SIZE); -	tfd = iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr); +	tfd = iwl_pcie_get_tfd(trans, txq, txq->write_ptr);  	/* Set up entry for this TFD in Tx byte-count array */  	iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len),  					 iwl_pcie_tfd_get_num_tbs(trans, tfd)); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 10b075a46b26..e8189c07b41f 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -684,6 +684,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,  	hdr = skb_put(skb, sizeof(*hdr) - ETH_ALEN);  	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |  					 IEEE80211_STYPE_NULLFUNC | +					 IEEE80211_FCTL_TODS |  					 (ps ? IEEE80211_FCTL_PM : 0));  	hdr->duration_id = cpu_to_le16(0);  	memcpy(hdr->addr1, vp->bssid, ETH_ALEN); @@ -3215,7 +3216,7 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)  		if (!net_eq(wiphy_net(data->hw->wiphy), genl_info_net(info)))  			continue; -		skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); +		skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);  		if (!skb) {  			res = -ENOMEM;  			goto out_err; diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c index 03687a80d6e9..38678e9a0562 100644 --- a/drivers/net/wireless/st/cw1200/sta.c +++ b/drivers/net/wireless/st/cw1200/sta.c @@ -198,7 +198,7 @@ void __cw1200_cqm_bssloss_sm(struct cw1200_common *priv,  		priv->bss_loss_state++; -		skb = ieee80211_nullfunc_get(priv->hw, priv->vif); +		skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false);  		WARN_ON(!skb);  		if (skb)  			cw1200_tx(priv->hw, NULL, skb); @@ -2265,7 +2265,7 @@ static int cw1200_upload_null(struct cw1200_common *priv)  		.rate = 0xFF,  	}; -	frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif); +	frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false);  	if (!frame.skb)  		return -ENOMEM; diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 9915d83a4a30..6d02c660b4ab 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c @@ -566,7 +566,7 @@ static int wl1251_build_null_data(struct wl1251 *wl)  		size = sizeof(struct wl12xx_null_data_template);  		ptr = NULL;  	} else { -		skb = ieee80211_nullfunc_get(wl->hw, wl->vif); +		skb = ieee80211_nullfunc_get(wl->hw, wl->vif, false);  		if (!skb)  			goto out;  		size = skb->len; diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 2bfc12fdc929..761cf8573a80 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -1069,7 +1069,8 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif)  		ptr = NULL;  	} else {  		skb = ieee80211_nullfunc_get(wl->hw, -					     wl12xx_wlvif_to_vif(wlvif)); +					     wl12xx_wlvif_to_vif(wlvif), +					     false);  		if (!skb)  			goto out;  		size = skb->len; @@ -1096,7 +1097,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl,  	struct sk_buff *skb = NULL;  	int ret = -ENOMEM; -	skb = ieee80211_nullfunc_get(wl->hw, vif); +	skb = ieee80211_nullfunc_get(wl->hw, vif, false);  	if (!skb)  		goto out;  | 

