iwl_read_prph() returns 0x5a5a5a5a when it cannot grab NIC access, which reads as "no CSME"; an all-ones CSR_HW_IF_CONFIG_REG reads as "CSME present". me_present is never recomputed and gates the reset ladder, so one bad read skews it for good. Reject both values. This does downgrade a product reset that a poisoned read used to permit. Cc: stable@vger.kernel.org Fixes: 41fff83fe6cd ("wifi: iwlwifi: pcie: check for WiAMT/CSME presence") Signed-off-by: Navon John Lukose --- Applies as-is to 6.18.y and 7.2.y. .../net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c index a30854d..e5edcc2 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -4194,7 +4194,8 @@ static void iwl_pcie_recheck_me_status(struct work_struct *wk) u32 val; val = iwl_read32(trans_pcie->trans, CSR_HW_IF_CONFIG_REG); - trans_pcie->me_present = !!(val & CSR_HW_IF_CONFIG_REG_IAMT_UP); + if (!PCI_POSSIBLE_ERROR(val)) + trans_pcie->me_present = !!(val & CSR_HW_IF_CONFIG_REG_IAMT_UP); } static void iwl_pcie_check_me_status(struct iwl_trans *trans) @@ -4212,15 +4213,19 @@ static void iwl_pcie_check_me_status(struct iwl_trans *trans) return; val = iwl_read_prph(trans, CNVI_SCU_REG_FOR_ECO_1); - if (val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_KNOWN) { + /* iwl_read_prph() returns 0x5a5a5a5a if it never reached the NIC, and + * that value has WIAMT_KNOWN set and WIAMT_PRESENT clear + */ + if (!PCI_POSSIBLE_ERROR(val) && !iwl_trans_is_hw_error_value(val) && + (val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_KNOWN)) { trans_pcie->me_present = !!(val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_PRESENT); return; } val = iwl_read32(trans, CSR_HW_IF_CONFIG_REG); - if (val & (CSR_HW_IF_CONFIG_REG_ME_OWN | - CSR_HW_IF_CONFIG_REG_IAMT_UP)) { + if (!PCI_POSSIBLE_ERROR(val) && (val & (CSR_HW_IF_CONFIG_REG_ME_OWN | + CSR_HW_IF_CONFIG_REG_IAMT_UP))) { trans_pcie->me_present = 1; return; }