Commit 906d4eb8 authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho
Browse files

iwlwifi: support firmware reset handshake



There are some races in the hardware that can possibly lead to
a bus lockup later during a restart when we manage to kill the
firmware at a bad time (while it's accessing the bus).

To work around this, add support for a new handshake between
firmware and driver to ensure that the firmware is in a well-
known state before we kill it.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20201209231352.7756fcc9865c.I13de65e0ffcb4186dd4c1a465f66df2e98c9a947@changeid


Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent b2ed841e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -359,6 +359,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
 *	initiator and responder
 * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload
 * @IWL_UCODE_TLV_CAPA_PROTECTED_TWT: Supports protection of TWT action frames
 * @IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE: Supports the firmware handshake in
 *	reset flow
 *
 * @NUM_IWL_UCODE_TLV_CAPA: number of bits used
 */
@@ -404,6 +406,7 @@ enum iwl_ucode_tlv_capa {
	IWL_UCODE_TLV_CAPA_TAS_CFG			= (__force iwl_ucode_tlv_capa_t)53,
	IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD		= (__force iwl_ucode_tlv_capa_t)54,
	IWL_UCODE_TLV_CAPA_PROTECTED_TWT		= (__force iwl_ucode_tlv_capa_t)56,
	IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE		= (__force iwl_ucode_tlv_capa_t)57,

	/* set 2 */
	IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE		= (__force iwl_ucode_tlv_capa_t)64,
+1 −0
Original line number Diff line number Diff line
@@ -583,6 +583,7 @@ enum msix_hw_int_causes {
	MSIX_HW_INT_CAUSES_REG_ALIVE		= BIT(0),
	MSIX_HW_INT_CAUSES_REG_WAKEUP		= BIT(1),
	MSIX_HW_INT_CAUSES_REG_IML              = BIT(1),
	MSIX_HW_INT_CAUSES_REG_RESET_DONE	= BIT(2),
	MSIX_HW_INT_CAUSES_REG_CT_KILL		= BIT(6),
	MSIX_HW_INT_CAUSES_REG_RF_KILL		= BIT(7),
	MSIX_HW_INT_CAUSES_REG_PERIODIC		= BIT(8),
+2 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@
/* Device NMI register and value for 9000 family and above hw's */
#define UREG_NIC_SET_NMI_DRIVER 0x00a05c10
#define UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER BIT(24)
#define UREG_NIC_SET_NMI_DRIVER_RESET_HANDSHAKE (BIT(24) | BIT(25))

/* Shared registers (0x0..0x3ff, via target indirect or periphery */
#define SHR_BASE	0x00a10000
@@ -399,6 +400,7 @@ enum {

#define UREG_DOORBELL_TO_ISR6		0xA05C04
#define UREG_DOORBELL_TO_ISR6_NMI_BIT	BIT(0)
#define UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE (BIT(0) | BIT(1))
#define UREG_DOORBELL_TO_ISR6_SUSPEND	BIT(18)
#define UREG_DOORBELL_TO_ISR6_RESUME	BIT(19)
#define UREG_DOORBELL_TO_ISR6_PNVM	BIT(20)
+2 −0
Original line number Diff line number Diff line
@@ -380,6 +380,7 @@ struct iwl_hcmd_arr {
 * @command_groups_size: number of command groups, to avoid illegal access
 * @cb_data_offs: offset inside skb->cb to store transport data at, must have
 *	space for at least two pointers
 * @fw_reset_handshake: firmware supports reset flow handshake
 */
struct iwl_trans_config {
	struct iwl_op_mode *op_mode;
@@ -397,6 +398,7 @@ struct iwl_trans_config {
	int command_groups_size;

	u8 cb_data_offs;
	bool fw_reset_handshake;
};

struct iwl_trans_dump_data {
+3 −0
Original line number Diff line number Diff line
@@ -728,6 +728,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
		 sizeof(mvm->hw->wiphy->fw_version),
		 "%s", fw->fw_version);

	trans_cfg.fw_reset_handshake = fw_has_capa(&mvm->fw->ucode_capa,
						   IWL_UCODE_TLV_CAPA_FW_RESET_HANDSHAKE);

	/* Configure transport layer */
	iwl_trans_configure(mvm->trans, &trans_cfg);

Loading