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

Commit b8a7547d authored by Shahar S Matityahu's avatar Shahar S Matityahu Committed by Luca Coelho
Browse files

iwlwifi: fix send hcmd timeout recovery flow



Both iwl_trans_fw_error and iwl_force_nmi initiate async recovery flow.
Calling them both is redundant and causing a race.

Solve this by removing the call to iwl_trans_fw_error.

Signed-off-by: default avatarShahar S Matityahu <shahar.s.matityahu@intel.com>
Fixes: cfadc3ff ("iwlwifi: pcie: stop the firmware when we restart it")
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 505a00c0
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -688,6 +688,9 @@ enum iwl_plat_pm_mode {
 */
#define IWL_TRANS_IDLE_TIMEOUT 2000

/* Max time to wait for nmi interrupt */
#define IWL_TRANS_NMI_TIMEOUT (HZ / 4)

/**
 * struct iwl_dram_data
 * @physical: page phy pointer
+1 −0
Original line number Diff line number Diff line
@@ -1036,6 +1036,7 @@ static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans)

void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
void iwl_trans_pcie_dump_regs(struct iwl_trans *trans);
void iwl_trans_sync_nmi(struct iwl_trans *trans);

#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
+25 −0
Original line number Diff line number Diff line
@@ -3650,3 +3650,28 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
	iwl_trans_free(trans);
	return ERR_PTR(ret);
}

void iwl_trans_sync_nmi(struct iwl_trans *trans)
{
	unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;

	iwl_disable_interrupts(trans);
	iwl_force_nmi(trans);
	while (time_after(timeout, jiffies)) {
		u32 inta_hw = iwl_read32(trans,
					 CSR_MSIX_HW_INT_CAUSES_AD);

		/* Error detected by uCode */
		if (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR) {
			/* Clear causes register */
			iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD,
				    inta_hw &
				    MSIX_HW_INT_CAUSES_REG_SW_ERR);
			break;
		}

		mdelay(1);
	}
	iwl_enable_interrupts(trans);
	iwl_trans_fw_error(trans);
}
+3 −5
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@
 * GPL LICENSE SUMMARY
 *
 * Copyright(c) 2017 Intel Deutschland GmbH
 * Copyright(c) 2018        Intel Corporation
 * Copyright(c) 2018 - 2019 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
@@ -20,7 +20,7 @@
 * BSD LICENSE
 *
 * Copyright(c) 2017 Intel Deutschland GmbH
 * Copyright(c) 2018        Intel Corporation
 * Copyright(c) 2018 - 2019 Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -965,9 +965,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans,
			       cmd_str);
		ret = -ETIMEDOUT;

		iwl_force_nmi(trans);
		iwl_trans_fw_error(trans);

		iwl_trans_sync_nmi(trans);
		goto cancel;
	}

+3 −5
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
 * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
 * Copyright(c) 2018 Intel Corporation
 * Copyright(c) 2018 - 2019 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
@@ -31,7 +31,7 @@
 * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
 * Copyright(c) 2018 Intel Corporation
 * Copyright(c) 2018 - 2019 Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -1942,9 +1942,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
			       iwl_get_cmd_string(trans, cmd->id));
		ret = -ETIMEDOUT;

		iwl_force_nmi(trans);
		iwl_trans_fw_error(trans);

		iwl_trans_sync_nmi(trans);
		goto cancel;
	}