diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c index 65aa9b9de487..c712a2654aec 100644 --- a/drivers/bus/mhi/host/boot.c +++ b/drivers/bus/mhi/host/boot.c @@ -299,17 +299,22 @@ static int mhi_fw_load_bhi(struct mhi_controller *mhi_cntrl, } void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info *image_info) + struct image_info **image_info) { int i; - struct mhi_buf *mhi_buf = image_info->mhi_buf; + struct mhi_buf *mhi_buf = (*image_info)->mhi_buf; - for (i = 0; i < image_info->entries; i++, mhi_buf++) + if (mhi_cntrl->img_pre_alloc) + return; + + for (i = 0; i < (*image_info)->entries; i++, mhi_buf++) dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len, mhi_buf->buf, mhi_buf->dma_addr); - kfree(image_info->mhi_buf); - kfree(image_info); + kfree((*image_info)->mhi_buf); + kfree(*image_info); + + *image_info = NULL; } int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, @@ -322,6 +327,9 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, struct image_info *img_info; struct mhi_buf *mhi_buf; + if (mhi_cntrl->img_pre_alloc) + return 0; + img_info = kzalloc(sizeof(*img_info), GFP_KERNEL); if (!img_info) return -ENOMEM; @@ -516,10 +524,8 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) return; error_ready_state: - if (mhi_cntrl->fbc_download) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); - mhi_cntrl->fbc_image = NULL; - } + if (mhi_cntrl->fbc_download) + mhi_free_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image); error_fw_load: mhi_cntrl->pm_state = MHI_PM_FW_DL_ERR; diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c index b5c696a4cb2a..6b660d014eea 100644 --- a/drivers/bus/mhi/host/init.c +++ b/drivers/bus/mhi/host/init.c @@ -1040,8 +1040,15 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl) unsigned int i; mhi_deinit_free_irq(mhi_cntrl); + /* Free the memory controller wanted to preserve for BHIe images */ + if (mhi_cntrl->img_pre_alloc) { + mhi_cntrl->img_pre_alloc = false; + if (mhi_cntrl->fbc_image) + mhi_free_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image); + if (mhi_cntrl->rddm_image) + mhi_free_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image); + } mhi_destroy_debugfs(mhi_cntrl); - destroy_workqueue(mhi_cntrl->hiprio_wq); kfree(mhi_cntrl->mhi_cmd); kfree(mhi_cntrl->mhi_event); @@ -1162,15 +1169,8 @@ EXPORT_SYMBOL_GPL(mhi_prepare_for_power_up); void mhi_unprepare_after_power_down(struct mhi_controller *mhi_cntrl) { - if (mhi_cntrl->fbc_image) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); - mhi_cntrl->fbc_image = NULL; - } - - if (mhi_cntrl->rddm_image) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->rddm_image); - mhi_cntrl->rddm_image = NULL; - } + if (mhi_cntrl->rddm_image) + mhi_free_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image); mhi_cntrl->bhi = NULL; mhi_cntrl->bhie = NULL; diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h index 3d62b836a67c..193a3493627e 100644 --- a/drivers/bus/mhi/host/internal.h +++ b/drivers/bus/mhi/host/internal.h @@ -277,7 +277,7 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl); int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, struct image_info **image_info, size_t alloc_size); void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info *image_info); + struct image_info **image_info); /* Power management APIs */ enum mhi_pm_state __must_check mhi_tryset_pm_state( diff --git a/drivers/bus/mhi/host/pm.c b/drivers/bus/mhi/host/pm.c index b60021d73efc..cda374bfc9ef 100644 --- a/drivers/bus/mhi/host/pm.c +++ b/drivers/bus/mhi/host/pm.c @@ -1186,6 +1186,8 @@ void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful) flush_work(&mhi_cntrl->st_worker); disable_irq(mhi_cntrl->irq[0]); + if (mhi_cntrl->fbc_image) + mhi_free_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image); } EXPORT_SYMBOL_GPL(mhi_power_down); diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 33952bfd76d9..e251cb6e9407 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -366,6 +366,7 @@ struct mhi_controller_config { * @reset: Controller specific reset function (optional) * @buffer_len: Bounce buffer length * @index: Index of the MHI controller instance + * @img_pre_alloc: allocate rddm and fbc image buffers one time * @bounce_buf: Use of bounce buffer * @fbc_download: MHI host needs to do complete image transfer (optional) * @wake_set: Device wakeup set flag @@ -461,6 +462,7 @@ struct mhi_controller { size_t buffer_len; int index; + bool img_pre_alloc; bool bounce_buf; bool fbc_download; bool wake_set;