diff --git a/drivers/bus/mhi/controllers/mhi_qcom.c b/drivers/bus/mhi/controllers/mhi_qcom.c index 7479dcef64de..cd252739c3a2 100644 --- a/drivers/bus/mhi/controllers/mhi_qcom.c +++ b/drivers/bus/mhi/controllers/mhi_qcom.c @@ -403,6 +403,11 @@ static int mhi_force_suspend(struct mhi_controller *mhi_cntrl) MHI_CNTRL_LOG("Entered\n"); + if (debug_mode == MHI_DEBUG_NO_D3 || debug_mode == MHI_FWIMAGE_NO_D3) { + MHI_CNTRL_LOG("Exited due to debug mode:%d\n", debug_mode); + return ret; + } + mutex_lock(&mhi_cntrl->pm_mutex); for (; itr; itr--) { @@ -676,7 +681,7 @@ static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev) bool use_s1; u32 addr_win[2]; const char *iommu_dma_type; - int ret, i; + int ret, i, len; if (!of_node) return ERR_PTR(-ENODEV); @@ -752,14 +757,22 @@ static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev) if (ret) goto error_register; - for (i = 0; i < ARRAY_SIZE(firmware_table); i++) { + len = ARRAY_SIZE(firmware_table); + for (i = 0; i < len; i++) { firmware_info = firmware_table + i; - /* debug mode always use default */ - if (!debug_mode && mhi_cntrl->dev_id == firmware_info->dev_id) + if (mhi_cntrl->dev_id == firmware_info->dev_id) break; } + if (debug_mode) { + if (debug_mode <= MHI_DEBUG_D3) + firmware_info = firmware_table + (len - 1); + MHI_CNTRL_LOG("fw info: debug_mode:%d dev_id:%d image:%s\n", + debug_mode, firmware_info->dev_id, + firmware_info->fw_image); + } + mhi_cntrl->fw_image = firmware_info->fw_image; mhi_cntrl->edl_image = firmware_info->edl_image; diff --git a/drivers/bus/mhi/controllers/mhi_qcom.h b/drivers/bus/mhi/controllers/mhi_qcom.h index 325be120486c..3b5e74b912c4 100644 --- a/drivers/bus/mhi/controllers/mhi_qcom.h +++ b/drivers/bus/mhi/controllers/mhi_qcom.h @@ -33,6 +33,15 @@ extern const char * const mhi_ee_str[MHI_EE_MAX]; #define TO_MHI_EXEC_STR(ee) (ee >= MHI_EE_MAX ? "INVALID_EE" : mhi_ee_str[ee]) +enum mhi_debug_mode { + MHI_DEBUG_MODE_OFF, + MHI_DEBUG_NO_D3, /* use debug.mbn as fw image and skip first M3/D3 */ + MHI_DEBUG_D3, /* use debug.mbn as fw image and allow first M3/D3 */ + MHI_FWIMAGE_NO_D3, /* use fw image if found and skip first M3/D3 */ + MHI_FWIMAGE_D3, /* use fw image if found and allow first M3/D3 */ + MHI_DEBUG_MODE_MAX = MHI_FWIMAGE_D3, +}; + enum mhi_suspend_mode { MHI_ACTIVE_STATE, MHI_DEFAULT_SUSPEND, diff --git a/drivers/bus/mhi/core/mhi_boot.c b/drivers/bus/mhi/core/mhi_boot.c index d5864a28548c..cfc37c975b26 100644 --- a/drivers/bus/mhi/core/mhi_boot.c +++ b/drivers/bus/mhi/core/mhi_boot.c @@ -278,6 +278,10 @@ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) void __iomem *base = mhi_cntrl->bhie; u32 rx_status; + /* device supports RDDM but controller wants to skip ramdumps */ + if (!mhi_cntrl->rddm_supported || !mhi_cntrl->rddm_image) + return -EINVAL; + if (in_panic) return __mhi_download_rddm_in_panic(mhi_cntrl); diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 7b0d2568bf2c..43b6a1de8618 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -1780,7 +1780,7 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) * allocate rddm table if specified, this table is for debug purpose * so we'll ignore erros */ - if (mhi_cntrl->rddm_size) { + if (mhi_cntrl->rddm_supported && mhi_cntrl->rddm_size) { mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image, mhi_cntrl->rddm_size); diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c index d7c064ef2d6e..8bf4db6fc7ad 100644 --- a/drivers/bus/mhi/core/mhi_main.c +++ b/drivers/bus/mhi/core/mhi_main.c @@ -1212,7 +1212,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, * event instead of sys error state change event */ if (mhi_cntrl->ee == MHI_EE_RDDM || - mhi_cntrl->rddm_image) + mhi_cntrl->rddm_supported) break; MHI_ERR("MHI system error detected\n"); @@ -1638,20 +1638,20 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) TO_MHI_EXEC_STR(ee), TO_MHI_STATE_STR(state)); - if (mhi_cntrl->power_down) { - write_unlock_irq(&mhi_cntrl->pm_lock); - goto exit_intvec; - } - if (state == MHI_STATE_SYS_ERR) { MHI_ERR("MHI system error detected\n"); pm_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_SYS_ERR_DETECT); } - write_unlock_irq(&mhi_cntrl->pm_lock); - if (ee == MHI_EE_RDDM) { - write_lock_irq(&mhi_cntrl->pm_lock); + if (mhi_cntrl->rddm_supported) { + /* exit as power down is already initiated */ + if (mhi_cntrl->power_down || ee != MHI_EE_RDDM) { + write_unlock_irq(&mhi_cntrl->pm_lock); + goto exit_intvec; + } + + /* prevent multiple entries for RDDM execution environment */ if (mhi_cntrl->ee == MHI_EE_RDDM) { write_unlock_irq(&mhi_cntrl->pm_lock); goto exit_intvec; @@ -1671,6 +1671,8 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) goto exit_intvec; } + write_unlock_irq(&mhi_cntrl->pm_lock); + /* if device is in RDDM, don't bother processing SYS_ERR */ if (ee != MHI_EE_RDDM && pm_state == MHI_PM_SYS_ERR_DETECT) { wake_up_all(&mhi_cntrl->state_event); diff --git a/drivers/bus/mhi/core/mhi_pm.c b/drivers/bus/mhi/core/mhi_pm.c index b0822bd1fbdf..67d5a109d5db 100644 --- a/drivers/bus/mhi/core/mhi_pm.c +++ b/drivers/bus/mhi/core/mhi_pm.c @@ -858,7 +858,7 @@ void mhi_process_sys_err(struct mhi_controller *mhi_cntrl) * if controller supports rddm, we do not process sys error state, * instead we will jump directly to rddm state */ - if (mhi_cntrl->rddm_image) { + if (mhi_cntrl->rddm_supported) { MHI_CNTRL_LOG( "Controller supports RDDM, skipping SYS_ERR_PROCESS\n"); return; @@ -1713,6 +1713,10 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_EXEC_STR(mhi_cntrl->ee)); + /* device does not support RDDM */ + if (!mhi_cntrl->rddm_supported) + return -EINVAL; + /* device already in rddm */ if (mhi_cntrl->ee == MHI_EE_RDDM) return 0; diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index f7040432f9ce..47e0279335ef 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -4464,6 +4464,7 @@ static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv) mhi_ctrl->sbl_size = SZ_512K; mhi_ctrl->seg_len = SZ_512K; mhi_ctrl->fbc_download = true; + mhi_ctrl->rddm_supported = true; mhi_ctrl->log_buf = ipc_log_context_create(CNSS_IPC_LOG_PAGES, "cnss-mhi", 0); diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 68658c297ca5..072e9bee5cc8 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -295,6 +295,7 @@ struct mhi_controller { /* mhi host manages downloading entire fbc images */ bool fbc_download; + bool rddm_supported; size_t rddm_size; size_t sbl_size; size_t seg_len;