Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91cf5ded authored by Johannes Berg's avatar Johannes Berg Committed by Kalle Valo
Browse files

iwlwifi: mvm: handle iwl_mvm_tvqm_enable_txq() error return



iwl_mvm_tvqm_enable_txq() can return an error, notably if unable
to allocate memory for the queue. Handle this error throughout,
avoiding storing the invalid value into a u16 which later leads
to a disable of an invalid queue ("queue 65524 not used", where
65524 is just -ENOMEM in a u16).

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent e5589015
Loading
Loading
Loading
Loading
+83 −57
Original line number Diff line number Diff line
@@ -1482,6 +1482,13 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
					    mvm_sta->sta_id, i);
			txq_id = iwl_mvm_tvqm_enable_txq(mvm, mvm_sta->sta_id,
							 i, wdg);
			/*
			 * on failures, just set it to IWL_MVM_INVALID_QUEUE
			 * to try again later, we have no other good way of
			 * failing here
			 */
			if (txq_id < 0)
				txq_id = IWL_MVM_INVALID_QUEUE;
			tid_data->txq_id = txq_id;

			/*
@@ -1950,20 +1957,12 @@ 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_snif_queue(struct iwl_mvm *mvm, u16 *queue,
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->trans->trans_cfg->base_params->wd_timeout :
		IWL_WATCHDOG_DISABLED;

	if (iwl_mvm_has_new_tx_api(mvm)) {
		int tvqm_queue =
			iwl_mvm_tvqm_enable_txq(mvm, sta_id,
						IWL_MAX_TID_COUNT,
						wdg_timeout);
		*queue = tvqm_queue;
	} else {
	struct iwl_trans_txq_scd_cfg cfg = {
		.fifo = fifo,
		.sta_id = sta_id,
@@ -1972,8 +1971,59 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue,
		.frame_limit = IWL_FRAME_LIMIT,
	};

		iwl_mvm_enable_txq(mvm, NULL, *queue, 0, &cfg, wdg_timeout);
	WARN_ON(iwl_mvm_has_new_tx_api(mvm));

	iwl_mvm_enable_txq(mvm, NULL, queue, 0, &cfg, wdg_timeout);
}

static int iwl_mvm_enable_aux_snif_queue_tvqm(struct iwl_mvm *mvm, u8 sta_id)
{
	unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
		mvm->trans->trans_cfg->base_params->wd_timeout :
		IWL_WATCHDOG_DISABLED;

	WARN_ON(!iwl_mvm_has_new_tx_api(mvm));

	return iwl_mvm_tvqm_enable_txq(mvm, sta_id, IWL_MAX_TID_COUNT,
				       wdg_timeout);
}

static int iwl_mvm_add_int_sta_with_queue(struct iwl_mvm *mvm, int macidx,
					  int maccolor,
					  struct iwl_mvm_int_sta *sta,
					  u16 *queue, int fifo)
{
	int ret;

	/* Map queue to fifo - needs to happen before adding station */
	if (!iwl_mvm_has_new_tx_api(mvm))
		iwl_mvm_enable_aux_snif_queue(mvm, *queue, sta->sta_id, fifo);

	ret = iwl_mvm_add_int_sta_common(mvm, sta, NULL, macidx, maccolor);
	if (ret) {
		if (!iwl_mvm_has_new_tx_api(mvm))
			iwl_mvm_disable_txq(mvm, NULL, *queue,
					    IWL_MAX_TID_COUNT, 0);
		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)) {
		int txq;

		txq = iwl_mvm_enable_aux_snif_queue_tvqm(mvm, sta->sta_id);
		if (txq < 0) {
			iwl_mvm_rm_sta_common(mvm, sta->sta_id);
			return txq;
		}

		*queue = txq;
	}

	return 0;
}

int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
@@ -1989,59 +2039,26 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
	if (ret)
		return ret;

	/* Map Aux queue to fifo - needs to happen before adding Aux station */
	if (!iwl_mvm_has_new_tx_api(mvm))
		iwl_mvm_enable_aux_snif_queue(mvm, &mvm->aux_queue,
					      mvm->aux_sta.sta_id,
	ret = iwl_mvm_add_int_sta_with_queue(mvm, MAC_INDEX_AUX, 0,
					     &mvm->aux_sta, &mvm->aux_queue,
					     IWL_MVM_TX_FIFO_MCAST);

	ret = iwl_mvm_add_int_sta_common(mvm, &mvm->aux_sta, NULL,
					 MAC_INDEX_AUX, 0);
	if (ret) {
		iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
		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->aux_queue,
					      mvm->aux_sta.sta_id,
					      IWL_MVM_TX_FIFO_MCAST);

	return 0;
}

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);

	/* 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,
	return iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, mvmvif->color,
					      &mvm->snif_sta, &mvm->snif_queue,
					      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)
@@ -2133,6 +2150,10 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
		queue = iwl_mvm_tvqm_enable_txq(mvm, bsta->sta_id,
						IWL_MAX_TID_COUNT,
						wdg_timeout);
		if (queue < 0) {
			iwl_mvm_rm_sta_common(mvm, bsta->sta_id);
			return queue;
		}

		if (vif->type == NL80211_IFTYPE_AP ||
		    vif->type == NL80211_IFTYPE_ADHOC)
@@ -2307,10 +2328,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
	}
	ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr,
					 mvmvif->id, mvmvif->color);
	if (ret) {
		iwl_mvm_dealloc_int_sta(mvm, msta);
		return ret;
	}
	if (ret)
		goto err;

	/*
	 * Enable cab queue after the ADD_STA command is sent.
@@ -2323,6 +2342,10 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
		int queue = iwl_mvm_tvqm_enable_txq(mvm, msta->sta_id,
						    0,
						    timeout);
		if (queue < 0) {
			ret = queue;
			goto err;
		}
		mvmvif->cab_queue = queue;
	} else if (!fw_has_api(&mvm->fw->ucode_capa,
			       IWL_UCODE_TLV_API_STA_TYPE))
@@ -2330,6 +2353,9 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
				   timeout);

	return 0;
err:
	iwl_mvm_dealloc_int_sta(mvm, msta);
	return ret;
}

static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,