diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/utils.c')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 453 | 
1 files changed, 10 insertions, 443 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index b002a7afb5f5..818e1180bbdd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -19,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.   * @@ -551,7 +546,6 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base)  	IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version); -	trace_iwlwifi_dev_ucode_error(trans->dev, &table, table.hw_ver, table.brd_ver);  	IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id,  		desc_lookup(table.error_id));  	IWL_ERR(mvm, "0x%08X | trm_hw_status0\n", table.trm_hw_status0); @@ -605,36 +599,6 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)  	iwl_mvm_dump_umac_error_log(mvm);  } -int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq) -{ -	int i; - -	lockdep_assert_held(&mvm->queue_info_lock); - -	/* This should not be hit with new TX path */ -	if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) -		return -ENOSPC; - -	/* Start by looking for a free queue */ -	for (i = minq; i <= maxq; i++) -		if (mvm->queue_info[i].hw_queue_refcount == 0 && -		    mvm->queue_info[i].status == IWL_MVM_QUEUE_FREE) -			return i; - -	/* -	 * If no free queue found - settle for an inactive one to reconfigure -	 * Make sure that the inactive queue either already belongs to this STA, -	 * or that if it belongs to another one - it isn't the reserved queue -	 */ -	for (i = minq; i <= maxq; i++) -		if (mvm->queue_info[i].status == IWL_MVM_QUEUE_INACTIVE && -		    (sta_id == mvm->queue_info[i].ra_sta_id || -		     !mvm->queue_info[i].reserved)) -			return i; - -	return -ENOSPC; -} -  int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,  			 int tid, int frame_limit, u16 ssn)  { @@ -655,7 +619,7 @@ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,  		return -EINVAL;  	spin_lock_bh(&mvm->queue_info_lock); -	if (WARN(mvm->queue_info[queue].hw_queue_refcount == 0, +	if (WARN(mvm->queue_info[queue].tid_bitmap == 0,  		 "Trying to reconfig unallocated queue %d\n", queue)) {  		spin_unlock_bh(&mvm->queue_info_lock);  		return -ENXIO; @@ -671,249 +635,21 @@ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,  	return ret;  } -static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue, -				       int mac80211_queue, u8 sta_id, u8 tid) -{ -	bool enable_queue = true; - -	spin_lock_bh(&mvm->queue_info_lock); - -	/* Make sure this TID isn't already enabled */ -	if (mvm->queue_info[queue].tid_bitmap & BIT(tid)) { -		spin_unlock_bh(&mvm->queue_info_lock); -		IWL_ERR(mvm, "Trying to enable TXQ %d with existing TID %d\n", -			queue, tid); -		return false; -	} - -	/* Update mappings and refcounts */ -	if (mvm->queue_info[queue].hw_queue_refcount > 0) -		enable_queue = false; - -	if (mac80211_queue != IEEE80211_INVAL_HW_QUEUE) { -		WARN(mac80211_queue >= -		     BITS_PER_BYTE * sizeof(mvm->hw_queue_to_mac80211[0]), -		     "cannot track mac80211 queue %d (queue %d, sta %d, tid %d)\n", -		     mac80211_queue, queue, sta_id, tid); -		mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue); -	} - -	mvm->queue_info[queue].hw_queue_refcount++; -	mvm->queue_info[queue].tid_bitmap |= BIT(tid); -	mvm->queue_info[queue].ra_sta_id = sta_id; - -	if (enable_queue) { -		if (tid != IWL_MAX_TID_COUNT) -			mvm->queue_info[queue].mac80211_ac = -				tid_to_mac80211_ac[tid]; -		else -			mvm->queue_info[queue].mac80211_ac = IEEE80211_AC_VO; - -		mvm->queue_info[queue].txq_tid = tid; -	} - -	IWL_DEBUG_TX_QUEUES(mvm, -			    "Enabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", -			    queue, mvm->queue_info[queue].hw_queue_refcount, -			    mvm->hw_queue_to_mac80211[queue]); - -	spin_unlock_bh(&mvm->queue_info_lock); - -	return enable_queue; -} - -int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue, -			    u8 sta_id, u8 tid, unsigned int timeout) -{ -	struct iwl_tx_queue_cfg_cmd cmd = { -		.flags = cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE), -		.sta_id = sta_id, -		.tid = tid, -	}; -	int queue, size = IWL_DEFAULT_QUEUE_SIZE; - -	if (cmd.tid == IWL_MAX_TID_COUNT) { -		cmd.tid = IWL_MGMT_TID; -		size = IWL_MGMT_QUEUE_SIZE; -	} -	queue = iwl_trans_txq_alloc(mvm->trans, (void *)&cmd, -				    SCD_QUEUE_CFG, size, timeout); - -	if (queue < 0) { -		IWL_DEBUG_TX_QUEUES(mvm, -				    "Failed allocating TXQ for sta %d tid %d, ret: %d\n", -				    sta_id, tid, queue); -		return queue; -	} - -	IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta %d tid %d\n", -			    queue, sta_id, tid); - -	mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue); -	IWL_DEBUG_TX_QUEUES(mvm, -			    "Enabling TXQ #%d (mac80211 map:0x%x)\n", -			    queue, mvm->hw_queue_to_mac80211[queue]); - -	return queue; -} - -bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, -			u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg, -			unsigned int wdg_timeout) -{ -	struct iwl_scd_txq_cfg_cmd cmd = { -		.scd_queue = queue, -		.action = SCD_CFG_ENABLE_QUEUE, -		.window = cfg->frame_limit, -		.sta_id = cfg->sta_id, -		.ssn = cpu_to_le16(ssn), -		.tx_fifo = cfg->fifo, -		.aggregate = cfg->aggregate, -		.tid = cfg->tid, -	}; -	bool inc_ssn; - -	if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) -		return false; - -	/* Send the enabling command if we need to */ -	if (!iwl_mvm_update_txq_mapping(mvm, queue, mac80211_queue, -					cfg->sta_id, cfg->tid)) -		return false; - -	inc_ssn = iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, -					   NULL, wdg_timeout); -	if (inc_ssn) -		le16_add_cpu(&cmd.ssn, 1); - -	WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd), -	     "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); - -	return inc_ssn; -} - -int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, -			u8 tid, u8 flags) -{ -	struct iwl_scd_txq_cfg_cmd cmd = { -		.scd_queue = queue, -		.action = SCD_CFG_DISABLE_QUEUE, -	}; -	bool remove_mac_queue = mac80211_queue != IEEE80211_INVAL_HW_QUEUE; -	int ret; - -	if (WARN_ON(remove_mac_queue && mac80211_queue >= IEEE80211_MAX_QUEUES)) -		return -EINVAL; - -	if (iwl_mvm_has_new_tx_api(mvm)) { -		spin_lock_bh(&mvm->queue_info_lock); - -		if (remove_mac_queue) -			mvm->hw_queue_to_mac80211[queue] &= -				~BIT(mac80211_queue); - -		spin_unlock_bh(&mvm->queue_info_lock); - -		iwl_trans_txq_free(mvm->trans, queue); - -		return 0; -	} - -	spin_lock_bh(&mvm->queue_info_lock); - -	if (WARN_ON(mvm->queue_info[queue].hw_queue_refcount == 0)) { -		spin_unlock_bh(&mvm->queue_info_lock); -		return 0; -	} - -	mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); - -	/* -	 * If there is another TID with the same AC - don't remove the MAC queue -	 * from the mapping -	 */ -	if (tid < IWL_MAX_TID_COUNT) { -		unsigned long tid_bitmap = -			mvm->queue_info[queue].tid_bitmap; -		int ac = tid_to_mac80211_ac[tid]; -		int i; - -		for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT) { -			if (tid_to_mac80211_ac[i] == ac) -				remove_mac_queue = false; -		} -	} - -	if (remove_mac_queue) -		mvm->hw_queue_to_mac80211[queue] &= -			~BIT(mac80211_queue); -	mvm->queue_info[queue].hw_queue_refcount--; - -	cmd.action = mvm->queue_info[queue].hw_queue_refcount ? -		SCD_CFG_ENABLE_QUEUE : SCD_CFG_DISABLE_QUEUE; -	if (cmd.action == SCD_CFG_DISABLE_QUEUE) -		mvm->queue_info[queue].status = IWL_MVM_QUEUE_FREE; - -	IWL_DEBUG_TX_QUEUES(mvm, -			    "Disabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", -			    queue, -			    mvm->queue_info[queue].hw_queue_refcount, -			    mvm->hw_queue_to_mac80211[queue]); - -	/* If the queue is still enabled - nothing left to do in this func */ -	if (cmd.action == SCD_CFG_ENABLE_QUEUE) { -		spin_unlock_bh(&mvm->queue_info_lock); -		return 0; -	} - -	cmd.sta_id = mvm->queue_info[queue].ra_sta_id; -	cmd.tid = mvm->queue_info[queue].txq_tid; - -	/* Make sure queue info is correct even though we overwrite it */ -	WARN(mvm->queue_info[queue].hw_queue_refcount || -	     mvm->queue_info[queue].tid_bitmap || -	     mvm->hw_queue_to_mac80211[queue], -	     "TXQ #%d info out-of-sync - refcount=%d, mac map=0x%x, tid=0x%x\n", -	     queue, mvm->queue_info[queue].hw_queue_refcount, -	     mvm->hw_queue_to_mac80211[queue], -	     mvm->queue_info[queue].tid_bitmap); - -	/* If we are here - the queue is freed and we can zero out these vals */ -	mvm->queue_info[queue].hw_queue_refcount = 0; -	mvm->queue_info[queue].tid_bitmap = 0; -	mvm->hw_queue_to_mac80211[queue] = 0; - -	/* Regardless if this is a reserved TXQ for a STA - mark it as false */ -	mvm->queue_info[queue].reserved = false; - -	spin_unlock_bh(&mvm->queue_info_lock); - -	iwl_trans_txq_disable(mvm->trans, queue, false); -	ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, -				   sizeof(struct iwl_scd_txq_cfg_cmd), &cmd); - -	if (ret) -		IWL_ERR(mvm, "Failed to disable queue %d (ret=%d)\n", -			queue, ret); -	return ret; -} -  /**   * iwl_mvm_send_lq_cmd() - Send link quality command - * @init: This command is sent as part of station initialization right - *        after station has been added. + * @sync: This command can be sent synchronously.   *   * The link quality command is sent as the last step of station creation.   * This is the special case in which init is set and we call a callback in   * this case to clear the state indicating that station creation is in   * progress.   */ -int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init) +int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync)  {  	struct iwl_host_cmd cmd = {  		.id = LQ_CMD,  		.len = { sizeof(struct iwl_lq_cmd), }, -		.flags = init ? 0 : CMD_ASYNC, +		.flags = sync ? 0 : CMD_ASYNC,  		.data = { lq, },  	}; @@ -1249,14 +985,12 @@ void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	struct iwl_fw_dbg_trigger_tlv *trig;  	struct iwl_fw_dbg_trigger_mlme *trig_mlme; -	if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME)) +	trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), +				     FW_DBG_TRIGGER_MLME); +	if (!trig)  		goto out; -	trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME);  	trig_mlme = (void *)trig->data; -	if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, -					   ieee80211_vif_to_wdev(vif), trig)) -		goto out;  	if (trig_mlme->stop_connection_loss &&  	    --trig_mlme->stop_connection_loss) @@ -1268,171 +1002,6 @@ out:  	ieee80211_connection_loss(vif);  } -/* - * Remove inactive TIDs of a given queue. - * If all queue TIDs are inactive - mark the queue as inactive - * If only some the queue TIDs are inactive - unmap them from the queue - */ -static void iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm, -					 struct iwl_mvm_sta *mvmsta, int queue, -					 unsigned long tid_bitmap) -{ -	int tid; - -	lockdep_assert_held(&mvmsta->lock); -	lockdep_assert_held(&mvm->queue_info_lock); - -	if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) -		return; - -	/* Go over all non-active TIDs, incl. IWL_MAX_TID_COUNT (for mgmt) */ -	for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { -		/* If some TFDs are still queued - don't mark TID as inactive */ -		if (iwl_mvm_tid_queued(mvm, &mvmsta->tid_data[tid])) -			tid_bitmap &= ~BIT(tid); - -		/* Don't mark as inactive any TID that has an active BA */ -		if (mvmsta->tid_data[tid].state != IWL_AGG_OFF) -			tid_bitmap &= ~BIT(tid); -	} - -	/* If all TIDs in the queue are inactive - mark queue as inactive. */ -	if (tid_bitmap == mvm->queue_info[queue].tid_bitmap) { -		mvm->queue_info[queue].status = IWL_MVM_QUEUE_INACTIVE; - -		for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) -			mvmsta->tid_data[tid].is_tid_active = false; - -		IWL_DEBUG_TX_QUEUES(mvm, "Queue %d marked as inactive\n", -				    queue); -		return; -	} - -	/* -	 * If we are here, this is a shared queue and not all TIDs timed-out. -	 * Remove the ones that did. -	 */ -	for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { -		int mac_queue = mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]]; - -		mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE; -		mvm->hw_queue_to_mac80211[queue] &= ~BIT(mac_queue); -		mvm->queue_info[queue].hw_queue_refcount--; -		mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); -		mvmsta->tid_data[tid].is_tid_active = false; - -		IWL_DEBUG_TX_QUEUES(mvm, -				    "Removing inactive TID %d from shared Q:%d\n", -				    tid, queue); -	} - -	IWL_DEBUG_TX_QUEUES(mvm, -			    "TXQ #%d left with tid bitmap 0x%x\n", queue, -			    mvm->queue_info[queue].tid_bitmap); - -	/* -	 * There may be different TIDs with the same mac queues, so make -	 * sure all TIDs have existing corresponding mac queues enabled -	 */ -	tid_bitmap = mvm->queue_info[queue].tid_bitmap; -	for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { -		mvm->hw_queue_to_mac80211[queue] |= -			BIT(mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]]); -	} - -	/* If the queue is marked as shared - "unshare" it */ -	if (mvm->queue_info[queue].hw_queue_refcount == 1 && -	    mvm->queue_info[queue].status == IWL_MVM_QUEUE_SHARED) { -		mvm->queue_info[queue].status = IWL_MVM_QUEUE_RECONFIGURING; -		IWL_DEBUG_TX_QUEUES(mvm, "Marking Q:%d for reconfig\n", -				    queue); -	} -} - -void iwl_mvm_inactivity_check(struct iwl_mvm *mvm) -{ -	unsigned long timeout_queues_map = 0; -	unsigned long now = jiffies; -	int i; - -	if (iwl_mvm_has_new_tx_api(mvm)) -		return; - -	spin_lock_bh(&mvm->queue_info_lock); -	for (i = 0; i < IWL_MAX_HW_QUEUES; i++) -		if (mvm->queue_info[i].hw_queue_refcount > 0) -			timeout_queues_map |= BIT(i); -	spin_unlock_bh(&mvm->queue_info_lock); - -	rcu_read_lock(); - -	/* -	 * If a queue time outs - mark it as INACTIVE (don't remove right away -	 * if we don't have to.) This is an optimization in case traffic comes -	 * later, and we don't HAVE to use a currently-inactive queue -	 */ -	for_each_set_bit(i, &timeout_queues_map, IWL_MAX_HW_QUEUES) { -		struct ieee80211_sta *sta; -		struct iwl_mvm_sta *mvmsta; -		u8 sta_id; -		int tid; -		unsigned long inactive_tid_bitmap = 0; -		unsigned long queue_tid_bitmap; - -		spin_lock_bh(&mvm->queue_info_lock); -		queue_tid_bitmap = mvm->queue_info[i].tid_bitmap; - -		/* If TXQ isn't in active use anyway - nothing to do here... */ -		if (mvm->queue_info[i].status != IWL_MVM_QUEUE_READY && -		    mvm->queue_info[i].status != IWL_MVM_QUEUE_SHARED) { -			spin_unlock_bh(&mvm->queue_info_lock); -			continue; -		} - -		/* Check to see if there are inactive TIDs on this queue */ -		for_each_set_bit(tid, &queue_tid_bitmap, -				 IWL_MAX_TID_COUNT + 1) { -			if (time_after(mvm->queue_info[i].last_frame_time[tid] + -				       IWL_MVM_DQA_QUEUE_TIMEOUT, now)) -				continue; - -			inactive_tid_bitmap |= BIT(tid); -		} -		spin_unlock_bh(&mvm->queue_info_lock); - -		/* If all TIDs are active - finish check on this queue */ -		if (!inactive_tid_bitmap) -			continue; - -		/* -		 * If we are here - the queue hadn't been served recently and is -		 * in use -		 */ - -		sta_id = mvm->queue_info[i].ra_sta_id; -		sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); - -		/* -		 * If the STA doesn't exist anymore, it isn't an error. It could -		 * be that it was removed since getting the queues, and in this -		 * case it should've inactivated its queues anyway. -		 */ -		if (IS_ERR_OR_NULL(sta)) -			continue; - -		mvmsta = iwl_mvm_sta_from_mac80211(sta); - -		spin_lock_bh(&mvmsta->lock); -		spin_lock(&mvm->queue_info_lock); -		iwl_mvm_remove_inactive_tids(mvm, mvmsta, i, -					     inactive_tid_bitmap); -		spin_unlock(&mvm->queue_info_lock); -		spin_unlock_bh(&mvmsta->lock); -	} - -	rcu_read_unlock(); -} -  void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,  					  struct ieee80211_vif *vif,  					  const struct ieee80211_sta *sta, @@ -1441,14 +1010,12 @@ void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,  	struct iwl_fw_dbg_trigger_tlv *trig;  	struct iwl_fw_dbg_trigger_ba *ba_trig; -	if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA)) +	trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), +				     FW_DBG_TRIGGER_BA); +	if (!trig)  		return; -	trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA);  	ba_trig = (void *)trig->data; -	if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, -					   ieee80211_vif_to_wdev(vif), trig)) -		return;  	if (!(le16_to_cpu(ba_trig->frame_timeout) & BIT(tid)))  		return;  |