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

Commit 0e39eb03 authored by Chaya Rachel Ivgi's avatar Chaya Rachel Ivgi Committed by Emmanuel Grumbach
Browse files

iwlwifi: mvm: Add a station in monitor mode

Currently when creating a new vif in monitor mode the driver doesn't
allocate a specific station. This causes that in the situation that
tx traffic is injected, the tx queues are not scheduled,
with the result of a TFD queue hang.
Fix that by allocating a station and ensuring its tx queues
are scheduled.

This fixes https://bugzilla.kernel.org/show_bug.cgi?id=104591



Signed-off-by: default avatarChaya Rachel Ivgi <chaya.rachel.ivgi@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent c3e230b1
Loading
Loading
Loading
Loading
+15 −1
Original line number Original line Diff line number Diff line
@@ -855,11 +855,17 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
					 u32 action)
					 u32 action)
{
{
	struct iwl_mac_ctx_cmd cmd = {};
	struct iwl_mac_ctx_cmd cmd = {};
	u32 tfd_queue_msk = 0;
	int ret, i;


	WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
	WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);


	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);


	for (i = 0; i < IEEE80211_NUM_ACS; i++)
		if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
			tfd_queue_msk |= BIT(vif->hw_queue[i]);

	cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
	cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
				       MAC_FILTER_IN_CONTROL_AND_MGMT |
				       MAC_FILTER_IN_CONTROL_AND_MGMT |
				       MAC_FILTER_IN_BEACON |
				       MAC_FILTER_IN_BEACON |
@@ -867,6 +873,12 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
				       MAC_FILTER_IN_CRC32);
				       MAC_FILTER_IN_CRC32);
	ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
	ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);


	/* Allocate sniffer station */
	ret = iwl_mvm_allocate_int_sta(mvm, &mvm->snif_sta, tfd_queue_msk,
				       vif->type);
	if (ret)
		return ret;

	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
}


@@ -1289,8 +1301,10 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)


	mvmvif->uploaded = false;
	mvmvif->uploaded = false;


	if (vif->type == NL80211_IFTYPE_MONITOR)
	if (vif->type == NL80211_IFTYPE_MONITOR) {
		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
		__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
		iwl_mvm_dealloc_snif_sta(mvm);
	}


	return 0;
	return 0;
}
}
+6 −0
Original line number Original line Diff line number Diff line
@@ -3126,6 +3126,11 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
		ret = iwl_mvm_update_quotas(mvm, false, NULL);
		ret = iwl_mvm_update_quotas(mvm, false, NULL);
		if (ret)
		if (ret)
			goto out_remove_binding;
			goto out_remove_binding;

		ret = iwl_mvm_add_snif_sta(mvm, vif);
		if (ret)
			goto out_remove_binding;

	}
	}


	/* Handle binding during CSA */
	/* Handle binding during CSA */
@@ -3199,6 +3204,7 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
	case NL80211_IFTYPE_MONITOR:
	case NL80211_IFTYPE_MONITOR:
		mvmvif->monitor_active = false;
		mvmvif->monitor_active = false;
		mvmvif->ps_disabled = false;
		mvmvif->ps_disabled = false;
		iwl_mvm_rm_snif_sta(mvm, vif);
		break;
		break;
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_AP:
		/* This part is triggered only during CSA */
		/* This part is triggered only during CSA */
+1 −0
Original line number Original line Diff line number Diff line
@@ -677,6 +677,7 @@ struct iwl_mvm {


	/* Internal station */
	/* Internal station */
	struct iwl_mvm_int_sta aux_sta;
	struct iwl_mvm_int_sta aux_sta;
	struct iwl_mvm_int_sta snif_sta;


	bool last_ebs_successful;
	bool last_ebs_successful;


+30 −3
Original line number Original line Diff line number Diff line
@@ -581,7 +581,7 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm,
	return ret;
	return ret;
}
}


static int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
			     struct iwl_mvm_int_sta *sta,
			     struct iwl_mvm_int_sta *sta,
			     u32 qmask, enum nl80211_iftype iftype)
			     u32 qmask, enum nl80211_iftype iftype)
{
{
@@ -673,6 +673,33 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
	return ret;
	return ret;
}
}


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

	lockdep_assert_held(&mvm->mutex);
	return iwl_mvm_add_int_sta_common(mvm, &mvm->snif_sta, vif->addr,
					 mvmvif->id, 0);
}

int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
	int ret;

	lockdep_assert_held(&mvm->mutex);

	ret = iwl_mvm_rm_sta_common(mvm, mvm->snif_sta.sta_id);
	if (ret)
		IWL_WARN(mvm, "Failed sending remove station\n");

	return ret;
}

void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm)
{
	iwl_mvm_dealloc_int_sta(mvm, &mvm->snif_sta);
}

void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm)
void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm)
{
{
	lockdep_assert_held(&mvm->mutex);
	lockdep_assert_held(&mvm->mutex);
+6 −0
Original line number Original line Diff line number Diff line
@@ -407,7 +407,13 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
			     struct iwl_mvm_int_sta *sta,
				    u32 qmask, enum nl80211_iftype iftype);
void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm);


void iwl_mvm_sta_drained_wk(struct work_struct *wk);
void iwl_mvm_sta_drained_wk(struct work_struct *wk);
void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,