提交 2aabdbdc 编写于 作者: E Emmanuel Grumbach 提交者: Luca Coelho

iwlwifi: pcie: enable interrupts before releasing the NIC's CPU

The NIC's CPU gets started after the firmware has been
written to its memory. The first thing it does is to
send an interrupt to let the driver know that it is
running. In order to get that interrupt, the driver needs
to make sure it is not masked. Of course, the interrupt
needs to be enabled in the driver before the CPU starts to
run.
I mistakenly inversed those two steps leading to races
which prevented the driver from getting the alive interrupt
from the firmware.
Fix that.

Cc: <stable@vger.kernel.org> [4.5+]
Fixes: a6bd005f ("iwlwifi: pcie: fix RF-Kill vs. firmware load race")
Signed-off-by: NEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: NLuca Coelho <luciano.coelho@intel.com>
上级 e34d975e
...@@ -801,6 +801,8 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans, ...@@ -801,6 +801,8 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
*first_ucode_section = last_read_idx; *first_ucode_section = last_read_idx;
iwl_enable_interrupts(trans);
if (cpu == 1) if (cpu == 1)
iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, 0xFFFF); iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, 0xFFFF);
else else
...@@ -980,6 +982,8 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, ...@@ -980,6 +982,8 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
iwl_pcie_apply_destination(trans); iwl_pcie_apply_destination(trans);
} }
iwl_enable_interrupts(trans);
/* release CPU reset */ /* release CPU reset */
iwl_write32(trans, CSR_RESET, 0); iwl_write32(trans, CSR_RESET, 0);
...@@ -1215,7 +1219,6 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, ...@@ -1215,7 +1219,6 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
ret = iwl_pcie_load_given_ucode_8000(trans, fw); ret = iwl_pcie_load_given_ucode_8000(trans, fw);
else else
ret = iwl_pcie_load_given_ucode(trans, fw); ret = iwl_pcie_load_given_ucode(trans, fw);
iwl_enable_interrupts(trans);
/* re-check RF-Kill state since we may have missed the interrupt */ /* re-check RF-Kill state since we may have missed the interrupt */
hw_rfkill = iwl_is_rfkill_set(trans); hw_rfkill = iwl_is_rfkill_set(trans);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册