Commit d48ff3ce authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Johannes Berg
Browse files

wifi: iwlwifi: mvm: don't dump the firmware state upon RFKILL while suspend



This is not really a firmware error. We need to reload the firmware, but
this doesn't mean that we should consider this as a firmware error.
When the firmware was restarted upon resume, this wasn't felt by the
driver. Now that we keep the firmware running during suspend even if we
don't have wowlan, this started to pop-up.

Fixes: e8bb19c1 ("wifi: iwlwifi: support fast resume")
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250209143303.a10463a40318.I14131781c3124b58e60e1f5e9d793a2bc88b464c@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent f9751163
Loading
Loading
Loading
Loading
+51 −26
Original line number Diff line number Diff line
@@ -3092,7 +3092,13 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
		ieee80211_resume_disconnect(vif);
}

static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
enum rt_status {
	FW_ALIVE,
	FW_NEEDS_RESET,
	FW_ERROR,
};

static enum rt_status iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
					      struct ieee80211_vif *vif)
{
	u32 err_id;
@@ -3101,29 +3107,35 @@ static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
	if (iwl_fwrt_read_err_table(mvm->trans,
				    mvm->trans->dbg.lmac_error_event_table[0],
				    &err_id)) {
		if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN && vif) {
		if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
			IWL_WARN(mvm, "Rfkill was toggled during suspend\n");
			if (vif) {
				struct cfg80211_wowlan_wakeup wakeup = {
					.rfkill_release = true,
				};

				ieee80211_report_wowlan_wakeup(vif, &wakeup,
							       GFP_KERNEL);
			}
		return true;

			return FW_NEEDS_RESET;
		}
		return FW_ERROR;
	}

	/* check if we have lmac2 set and check for error */
	if (iwl_fwrt_read_err_table(mvm->trans,
				    mvm->trans->dbg.lmac_error_event_table[1],
				    NULL))
		return true;
		return FW_ERROR;

	/* check for umac error */
	if (iwl_fwrt_read_err_table(mvm->trans,
				    mvm->trans->dbg.umac_error_event_table,
				    NULL))
		return true;
		return FW_ERROR;

	return false;
	return FW_ALIVE;
}

/*
@@ -3492,6 +3504,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
	bool d0i3_first = fw_has_capa(&mvm->fw->ucode_capa,
				      IWL_UCODE_TLV_CAPA_D0I3_END_FIRST);
	bool resume_notif_based = iwl_mvm_d3_resume_notif_based(mvm);
	enum rt_status rt_status;
	bool keep = false;

	mutex_lock(&mvm->mutex);
@@ -3515,14 +3528,19 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)

	iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);

	if (iwl_mvm_check_rt_status(mvm, vif)) {
		IWL_ERR(mvm, "FW Error occurred during suspend. Restarting.\n");
	rt_status = iwl_mvm_check_rt_status(mvm, vif);
	if (rt_status != FW_ALIVE) {
		set_bit(STATUS_FW_ERROR, &mvm->trans->status);
		if (rt_status == FW_ERROR) {
			IWL_ERR(mvm, "FW Error occurred during suspend. Restarting.\n");
			iwl_mvm_dump_nic_error_log(mvm);
			iwl_dbg_tlv_time_point(&mvm->fwrt,
				       IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL);
		iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
					       IWL_FW_INI_TIME_POINT_FW_ASSERT,
					       NULL);
			iwl_fw_dbg_collect_desc(&mvm->fwrt,
						&iwl_dump_desc_assert,
						false, 0);
		}
		ret = 1;
		goto err;
	}
@@ -3679,6 +3697,7 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
		.notif_expected =
			IWL_D3_NOTIF_D3_END_NOTIF,
	};
	enum rt_status rt_status;
	int ret;

	lockdep_assert_held(&mvm->mutex);
@@ -3688,14 +3707,20 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
	mvm->last_reset_or_resume_time_jiffies = jiffies;
	iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);

	if (iwl_mvm_check_rt_status(mvm, NULL)) {
		IWL_ERR(mvm, "FW Error occurred during suspend. Restarting.\n");
	rt_status = iwl_mvm_check_rt_status(mvm, NULL);
	if (rt_status != FW_ALIVE) {
		set_bit(STATUS_FW_ERROR, &mvm->trans->status);
		if (rt_status == FW_ERROR) {
			IWL_ERR(mvm,
				"iwl_mvm_check_rt_status failed, device is gone during suspend\n");
			iwl_mvm_dump_nic_error_log(mvm);
			iwl_dbg_tlv_time_point(&mvm->fwrt,
				       IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL);
		iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
					       IWL_FW_INI_TIME_POINT_FW_ASSERT,
					       NULL);
			iwl_fw_dbg_collect_desc(&mvm->fwrt,
						&iwl_dump_desc_assert,
						false, 0);
		}
		mvm->trans->state = IWL_TRANS_NO_FW;
		ret = -ENODEV;