Commit 15eb5e3e authored by Kalle Valo's avatar Kalle Valo
Browse files

Merge tag 'iwlwifi-for-kalle-2018-03-19' of...

Merge tag 'iwlwifi-for-kalle-2018-03-19' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes

Fourth batch of iwlwifi fixes intended for 4.16:

* a couple of fixes for channel-switch;
* a few fixes for the aggregation handling code;
parents 12590551 9f4ef1d7
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -3494,6 +3494,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
		ret = 0;
		goto out;
	case NL80211_IFTYPE_STATION:
		mvmvif->csa_bcn_pending = false;
		break;
	case NL80211_IFTYPE_MONITOR:
		/* always disable PS when a monitor interface is active */
@@ -3537,7 +3538,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
	}

	if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
		u32 duration = 2 * vif->bss_conf.beacon_int;
		u32 duration = 3 * vif->bss_conf.beacon_int;

		/* iwl_mvm_protect_session() reads directly from the
		 * device (the system time), so make sure it is
@@ -3550,6 +3551,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
		/* Protect the session to make sure we hear the first
		 * beacon on the new channel.
		 */
		mvmvif->csa_bcn_pending = true;
		iwl_mvm_protect_session(mvm, vif, duration, duration,
					vif->bss_conf.beacon_int / 2,
					true);
@@ -3988,6 +3990,7 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
	if (vif->type == NL80211_IFTYPE_STATION) {
		struct iwl_mvm_sta *mvmsta;

		mvmvif->csa_bcn_pending = false;
		mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
							  mvmvif->ap_sta_id);

+3 −0
Original line number Diff line number Diff line
@@ -438,6 +438,9 @@ struct iwl_mvm_vif {
	bool csa_failed;
	u16 csa_target_freq;

	/* Indicates that we are waiting for a beacon on a new channel */
	bool csa_bcn_pending;

	/* TCP Checksum Offload */
	netdev_features_t features;
};
+16 −5
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
 * Copyright(c) 2017           Intel Deutschland GmbH
 * Copyright(c) 2018           Intel Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
@@ -18,11 +19,6 @@
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
 * USA
 *
 * The full GNU General Public License is included in this distribution
 * in the file called COPYING.
 *
@@ -34,6 +30,7 @@
 *
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
 * Copyright(c) 2018           Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -286,6 +283,20 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
		return;

	ctxt->ref--;

	/*
	 * Move unused phy's to a default channel. When the phy is moved the,
	 * fw will cleanup immediate quiet bit if it was previously set,
	 * otherwise we might not be able to reuse this phy.
	 */
	if (ctxt->ref == 0) {
		struct ieee80211_channel *chan;
		struct cfg80211_chan_def chandef;

		chan = &mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[0];
		cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
		iwl_mvm_phy_ctxt_changed(mvm, ctxt, &chandef, 1, 1);
	}
}

static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
+21 −32
Original line number Diff line number Diff line
@@ -1695,7 +1695,8 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
			     u32 qmask, enum nl80211_iftype iftype,
			     enum iwl_sta_type type)
{
	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
	if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
	    sta->sta_id == IWL_MVM_INVALID_STA) {
		sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype);
		if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA))
			return -ENOSPC;
@@ -2478,28 +2479,12 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

	/*
	 * Note the possible cases:
	 *  1. In DQA mode with an enabled TXQ - TXQ needs to become agg'ed
	 *  2. Non-DQA mode: the TXQ hasn't yet been enabled, so find a free
	 *	one and mark it as reserved
	 *  3. In DQA mode, but no traffic yet on this TID: same treatment as in
	 *	non-DQA mode, since the TXQ hasn't yet been allocated
	 * Don't support case 3 for new TX path as it is not expected to happen
	 * and aggregation will be offloaded soon anyway
	 *  1. An enabled TXQ - TXQ needs to become agg'ed
	 *  2. The TXQ hasn't yet been enabled, so find a free one and mark
	 *	it as reserved
	 */
	txq_id = mvmsta->tid_data[tid].txq_id;
	if (iwl_mvm_has_new_tx_api(mvm)) {
	if (txq_id == IWL_MVM_INVALID_QUEUE) {
			ret = -ENXIO;
			goto release_locks;
		}
	} else if (unlikely(mvm->queue_info[txq_id].status ==
			    IWL_MVM_QUEUE_SHARED)) {
		ret = -ENXIO;
		IWL_DEBUG_TX_QUEUES(mvm,
				    "Can't start tid %d agg on shared queue!\n",
				    tid);
		goto release_locks;
	} else if (mvm->queue_info[txq_id].status != IWL_MVM_QUEUE_READY) {
		txq_id = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id,
						 IWL_MVM_DQA_MIN_DATA_QUEUE,
						 IWL_MVM_DQA_MAX_DATA_QUEUE);
@@ -2508,16 +2493,16 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
			IWL_ERR(mvm, "Failed to allocate agg queue\n");
			goto release_locks;
		}
		/*
		 * TXQ shouldn't be in inactive mode for non-DQA, so getting
		 * an inactive queue from iwl_mvm_find_free_queue() is
		 * certainly a bug
		 */
		WARN_ON(mvm->queue_info[txq_id].status ==
			IWL_MVM_QUEUE_INACTIVE);

		/* TXQ hasn't yet been enabled, so mark it only as reserved */
		mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_RESERVED;
	} else if (unlikely(mvm->queue_info[txq_id].status ==
			    IWL_MVM_QUEUE_SHARED)) {
		ret = -ENXIO;
		IWL_DEBUG_TX_QUEUES(mvm,
				    "Can't start tid %d agg on shared queue!\n",
				    tid);
		goto release_locks;
	}

	spin_unlock(&mvm->queue_info_lock);
@@ -2696,8 +2681,10 @@ out:

static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
					struct iwl_mvm_sta *mvmsta,
					u16 txq_id)
					struct iwl_mvm_tid_data *tid_data)
{
	u16 txq_id = tid_data->txq_id;

	if (iwl_mvm_has_new_tx_api(mvm))
		return;

@@ -2709,8 +2696,10 @@ static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
	 * allocated through iwl_mvm_enable_txq, so we can just mark it back as
	 * free.
	 */
	if (mvm->queue_info[txq_id].status == IWL_MVM_QUEUE_RESERVED)
	if (mvm->queue_info[txq_id].status == IWL_MVM_QUEUE_RESERVED) {
		mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_FREE;
		tid_data->txq_id = IWL_MVM_INVALID_QUEUE;
	}

	spin_unlock_bh(&mvm->queue_info_lock);
}
@@ -2741,7 +2730,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,

	mvmsta->agg_tids &= ~BIT(tid);

	iwl_mvm_unreserve_agg_queue(mvm, mvmsta, txq_id);
	iwl_mvm_unreserve_agg_queue(mvm, mvmsta, tid_data);

	switch (tid_data->state) {
	case IWL_AGG_ON:
@@ -2808,7 +2797,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
	mvmsta->agg_tids &= ~BIT(tid);
	spin_unlock_bh(&mvmsta->lock);

	iwl_mvm_unreserve_agg_queue(mvm, mvmsta, txq_id);
	iwl_mvm_unreserve_agg_queue(mvm, mvmsta, tid_data);

	if (old_state >= IWL_AGG_ON) {
		iwl_mvm_drain_sta(mvm, mvmsta, true);
+8 −7
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
 * Copyright(c) 2017 Intel Deutschland GmbH
 * Copyright(c) 2018 Intel Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
@@ -18,11 +19,6 @@
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
 * USA
 *
 * The full GNU General Public License is included in this distribution
 * in the file called COPYING.
 *
@@ -35,6 +31,7 @@
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
 * Copyright(c) 2017 Intel Deutschland GmbH
 * Copyright(c) 2018 Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -198,9 +195,13 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
					struct ieee80211_vif *vif,
					const char *errmsg)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

	if (vif->type != NL80211_IFTYPE_STATION)
		return false;
	if (vif->bss_conf.assoc && vif->bss_conf.dtim_period)

	if (!mvmvif->csa_bcn_pending && vif->bss_conf.assoc &&
	    vif->bss_conf.dtim_period)
		return false;
	if (errmsg)
		IWL_ERR(mvm, "%s\n", errmsg);
@@ -344,7 +345,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
			 * and know the dtim period.
			 */
			iwl_mvm_te_check_disconnect(mvm, te_data->vif,
				"No association and the time event is over already...");
				"No beacon heard and the time event is over already...");
			break;
		default:
			break;