iwlwifi: use sync nmi in case of init flow failure

In case of alive interrupt timeout or any failure in the init flow
the driver generates FW nmi. The driver assumes that the nmi will
generate SW interrupt. This assumption does not hold and leads to faulty
behavior in the recovery flow.

Solve this by using sync nmi, this way, even if the driver does not
receive SW interrupt, it still starts the recovery flow.

Also remove the wait queue from iwl_fwrt_stop_device since the driver is
handling the SW interrupt synchronously.

Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
Shahar S Matityahu
2019-02-10 10:42:16 +02:00
کامیت شده توسط Luca Coelho
والد b05d57c9b6
کامیت 07d35b4270
3فایلهای تغییر یافته به همراه3 افزوده شده و 31 حذف شده

مشاهده پرونده

@@ -1944,14 +1944,10 @@ int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
iwl_dump_error_desc->len = 0;
ret = iwl_fw_dbg_collect_desc(fwrt, iwl_dump_error_desc, false, 0);
if (ret) {
if (ret)
kfree(iwl_dump_error_desc);
} else {
set_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status);
/* trigger nmi to halt the fw */
iwl_force_nmi(fwrt->trans);
}
else
iwl_trans_sync_nmi(fwrt->trans);
return ret;
}
@@ -2491,22 +2487,6 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt)
{
/* if the wait event timeout elapses instead of wake up then
* the driver did not receive NMI interrupt and can not assume the FW
* is halted
*/
int ret = wait_event_timeout(fwrt->trans->fw_halt_waitq,
!test_bit(STATUS_FW_WAIT_DUMP,
&fwrt->trans->status),
msecs_to_jiffies(2000));
if (!ret) {
/* failed to receive NMI interrupt, assuming the FW is stuck */
set_bit(STATUS_FW_ERROR, &fwrt->trans->status);
clear_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status);
}
/* Assuming the op mode mutex is held at this point */
iwl_fw_dbg_collect_sync(fwrt);
iwl_trans_stop_device(fwrt->trans);

مشاهده پرونده

@@ -76,7 +76,6 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
fwrt->ops_ctx = ops_ctx;
INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk);
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
init_waitqueue_head(&fwrt->trans->fw_halt_waitq);
}
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);