diff --git a/drivers/bus/mhi/core/mhi_boot.c b/drivers/bus/mhi/core/mhi_boot.c index 5df5ad6f985e..d5a90cb2ecb7 100644 --- a/drivers/bus/mhi/core/mhi_boot.c +++ b/drivers/bus/mhi/core/mhi_boot.c @@ -139,6 +139,31 @@ void mhi_dump_sfr(struct mhi_controller *mhi_cntrl) } EXPORT_SYMBOL(mhi_dump_sfr); +bool mhi_scan_rddm_cookie(struct mhi_controller *mhi_cntrl, u32 cookie) +{ + int ret; + u32 val; + + if (!mhi_cntrl->rddm_supported || !cookie) + return false; + + MHI_CNTRL_LOG("Checking BHI debug register for 0x%x\n", cookie); + + if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) + return false; + + ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_ERRDBG2, &val); + if (ret) + return false; + + MHI_CNTRL_LOG("BHI_ERRDBG2 value:0x%x\n", val); + if (val == cookie) + return true; + + return false; +} +EXPORT_SYMBOL(mhi_scan_rddm_cookie); + /* setup rddm vector table for rddm transfer and program rxvec */ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, struct image_info *img_info) @@ -444,6 +469,9 @@ void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, int i; struct mhi_buf *mhi_buf = image_info->mhi_buf; + if (!image_info) + return; + for (i = 0; i < image_info->entries; i++, mhi_buf++) mhi_free_contig_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf, mhi_buf->dma_addr); @@ -571,14 +599,14 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) !mhi_cntrl->seg_len))) { MHI_CNTRL_ERR( "No firmware image defined or !sbl_size || !seg_len\n"); - return; + goto fw_load_error; } ret = request_firmware(&firmware, fw_name, mhi_cntrl->dev); if (ret) { if (!mhi_cntrl->fw_image_fallback) { MHI_CNTRL_ERR("Error loading fw, ret:%d\n", ret); - return; + goto fw_load_error; } /* re-try with fall back fw image */ @@ -586,7 +614,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) mhi_cntrl->dev); if (ret) { MHI_CNTRL_ERR("Error loading fw_fb, ret:%d\n", ret); - return; + goto fw_load_error; } mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, @@ -602,8 +630,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) buf = mhi_alloc_coherent(mhi_cntrl, size, &dma_addr, GFP_KERNEL); if (!buf) { MHI_CNTRL_ERR("Could not allocate memory for image\n"); - release_firmware(firmware); - return; + goto fw_load_error_release; } /* load sbl or edl image via BHI */ @@ -611,17 +638,16 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) ret = mhi_fw_load_bhi(mhi_cntrl, dma_addr, size); mhi_free_coherent(mhi_cntrl, size, buf, dma_addr); - if (!mhi_cntrl->fbc_download || ret || mhi_cntrl->ee == MHI_EE_EDL) - release_firmware(firmware); - if (ret) { MHI_CNTRL_ERR("MHI did not load SBL/EDL image, ret:%d\n", ret); - return; + goto fw_load_error_release; } /* we are done with FW load is EE is EDL */ - if (mhi_cntrl->ee == MHI_EE_EDL) + if (mhi_cntrl->ee == MHI_EE_EDL) { + release_firmware(firmware); return; + } write_lock_irq(&mhi_cntrl->pm_lock); mhi_cntrl->dev_state = MHI_STATE_RESET; @@ -636,7 +662,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) firmware->size); if (ret) { MHI_CNTRL_ERR("Error alloc size:%zu\n", firmware->size); - goto error_alloc_fw_table; + goto fw_load_error_ready; } MHI_CNTRL_LOG("Copying firmware image into vector table\n"); @@ -645,6 +671,9 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) mhi_firmware_copy(mhi_cntrl, firmware, mhi_cntrl->fbc_image); } + release_firmware(firmware); + firmware = NULL; + fw_load_ee_pthru: /* transitioning into MHI RESET->READY state */ ret = mhi_ready_state_transition(mhi_cntrl); @@ -653,15 +682,14 @@ fw_load_ee_pthru: to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_STATE_STR(mhi_cntrl->dev_state), TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); - - if (!mhi_cntrl->fbc_download) - return; - if (ret) { MHI_CNTRL_ERR("Did not transition to READY state\n"); - goto error_read; + goto fw_load_error_ready; } + if (!mhi_cntrl->fbc_download || mhi_cntrl->ee == MHI_EE_PTHRU) + return; + /* wait for SBL event */ ret = wait_event_timeout(mhi_cntrl->state_event, mhi_cntrl->ee == MHI_EE_SBL || @@ -670,7 +698,7 @@ fw_load_ee_pthru: if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { MHI_CNTRL_ERR("MHI did not enter BHIE\n"); - goto error_read; + goto fw_load_error_ready; } /* start full firmware image download */ @@ -681,16 +709,23 @@ fw_load_ee_pthru: MHI_CNTRL_LOG("amss fw_load ret:%d\n", ret); - release_firmware(firmware); + if (ret) + goto fw_load_error; return; -error_read: +fw_load_error_ready: mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); mhi_cntrl->fbc_image = NULL; -error_alloc_fw_table: +fw_load_error_release: release_firmware(firmware); + +fw_load_error: + write_lock_irq(&mhi_cntrl->pm_lock); + mhi_cntrl->pm_state = MHI_PM_FW_DL_ERR; + wake_up_all(&mhi_cntrl->state_event); + write_unlock_irq(&mhi_cntrl->pm_lock); } void mhi_perform_soc_reset(struct mhi_controller *mhi_cntrl) diff --git a/drivers/bus/mhi/core/mhi_pm.c b/drivers/bus/mhi/core/mhi_pm.c index 9189e1b66ae2..43b19267a860 100644 --- a/drivers/bus/mhi/core/mhi_pm.c +++ b/drivers/bus/mhi/core/mhi_pm.c @@ -481,12 +481,15 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl) write_lock_irq(&mhi_cntrl->pm_lock); if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) ee = mhi_get_exec_env(mhi_cntrl); - write_unlock_irq(&mhi_cntrl->pm_lock); if (!MHI_IN_MISSION_MODE(ee)) { MHI_CNTRL_ERR("Invalid EE:%s\n", TO_MHI_EXEC_STR(ee)); + mhi_cntrl->pm_state = MHI_PM_FW_DL_ERR; + wake_up_all(&mhi_cntrl->state_event); + write_unlock_irq(&mhi_cntrl->pm_lock); return -EIO; } + write_unlock_irq(&mhi_cntrl->pm_lock); mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, MHI_CB_EE_MISSION_MODE); diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 84e4d5dcdafe..6e79d52d7050 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -797,6 +797,14 @@ int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_client); */ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic); +/** + * mhi_scan_rddm_cookie - Look for supplied cookie value in the BHI debug + * registers set by device to indicate rddm readiness for debugging purposes. + * @mhi_cntrl: MHI controller + * @cookie: cookie/pattern value to match + */ +bool mhi_scan_rddm_cookie(struct mhi_controller *mhi_cntrl, u32 cookie); + /** * mhi_force_rddm_mode - Force external device into rddm mode * to collect device ramdump. This is useful if host driver assert