summaryrefslogtreecommitdiff
path: root/drivers/platform
diff options
context:
space:
mode:
authorUtkarsh Saxena <usaxena@codeaurora.org>2017-05-03 14:04:30 +0530
committerUtkarsh Saxena <usaxena@codeaurora.org>2017-05-18 16:09:00 +0530
commit2931599ee9a0a58e2878a6d1757c1d32c5e11294 (patch)
tree52db74b38516d2432efad16ed61c31d275996c5d /drivers/platform
parentc01ba1a5f98de6e2f271cc2e447fe3280920cc16 (diff)
msm: ipa: Fix post init in workqueue context
ipa post init is accessed from user space context from ops structure. While user space program triggered post init there could be a chance, where the user space context may get killed at any time, due to which the memory allocation in post init gets failed and in turn which clean up the IPA driver. Because the memory allocation of the sigkill pending process will fail. Make changes in ops structure write func-pointer to queue a work instead of directly invoking post init. So that ipa post init will execute in workqueue context. Change-Id: Ia11b3a868d960111422c357bcc9924ef7b220e67 Acked-by: Mohammed Javid <mjavid@qti.qualcomm.com> Signed-off-by: Utkarsh Saxena <usaxena@codeaurora.org>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa.c105
1 files changed, 52 insertions, 53 deletions
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 5ee6e5d2d9e3..0f5f08bc0853 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -240,6 +240,9 @@ static void ipa_gsi_release_resource(struct work_struct *work);
static DECLARE_DELAYED_WORK(ipa_gsi_release_resource_work,
ipa_gsi_release_resource);
+static void ipa3_post_init_wq(struct work_struct *work);
+static DECLARE_WORK(ipa3_post_init_work, ipa3_post_init_wq);
+
static struct ipa3_plat_drv_res ipa3_res = {0, };
struct msm_bus_scale_pdata *ipa3_bus_scale_table;
@@ -3947,6 +3950,15 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
struct gsi_per_props gsi_props;
struct ipa3_uc_hdlrs uc_hdlrs = { 0 };
+ if (ipa3_ctx == NULL) {
+ IPADBG("IPA driver haven't initialized\n");
+ return -ENXIO;
+ }
+
+ /* Prevent consequent calls from trying to load the FW again. */
+ if (ipa3_ctx->ipa_initialization_complete)
+ return 0;
+
if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) {
memset(&gsi_props, 0, sizeof(gsi_props));
gsi_props.ver = ipa3_get_gsi_ver(resource_p->ipa_hw_type);
@@ -4059,40 +4071,14 @@ fail_setup_apps_pipes:
else
sps_deregister_bam_device(ipa3_ctx->bam_handle);
fail_register_device:
- ipa_rm_delete_resource(IPA_RM_RESOURCE_APPS_CONS);
- ipa_rm_exit();
- cdev_del(&ipa3_ctx->cdev);
- device_destroy(ipa3_ctx->class, ipa3_ctx->dev_num);
- unregister_chrdev_region(ipa3_ctx->dev_num, 1);
- if (ipa3_ctx->pipe_mem_pool)
- gen_pool_destroy(ipa3_ctx->pipe_mem_pool);
- ipa3_free_dma_task_for_gsi();
- ipa3_destroy_flt_tbl_idrs();
- idr_destroy(&ipa3_ctx->ipa_idr);
- kmem_cache_destroy(ipa3_ctx->rx_pkt_wrapper_cache);
- kmem_cache_destroy(ipa3_ctx->tx_pkt_wrapper_cache);
- kmem_cache_destroy(ipa3_ctx->rt_tbl_cache);
- kmem_cache_destroy(ipa3_ctx->hdr_proc_ctx_offset_cache);
- kmem_cache_destroy(ipa3_ctx->hdr_proc_ctx_cache);
- kmem_cache_destroy(ipa3_ctx->hdr_offset_cache);
- kmem_cache_destroy(ipa3_ctx->hdr_cache);
- kmem_cache_destroy(ipa3_ctx->rt_rule_cache);
- kmem_cache_destroy(ipa3_ctx->flt_rule_cache);
- destroy_workqueue(ipa3_ctx->transport_power_mgmt_wq);
- destroy_workqueue(ipa3_ctx->power_mgmt_wq);
- iounmap(ipa3_ctx->mmio);
- ipa3_disable_clks();
- msm_bus_scale_unregister_client(ipa3_ctx->ipa_bus_hdl);
- if (ipa3_bus_scale_table) {
- msm_bus_cl_clear_pdata(ipa3_bus_scale_table);
- ipa3_bus_scale_table = NULL;
- }
- kfree(ipa3_ctx->ctrl);
- kfree(ipa3_ctx);
- ipa3_ctx = NULL;
return result;
}
+static void ipa3_post_init_wq(struct work_struct *work)
+{
+ ipa3_post_init(&ipa3_res, ipa3_ctx->dev);
+}
+
static int ipa3_trigger_fw_loading_mdms(void)
{
int result;
@@ -4189,8 +4175,10 @@ static ssize_t ipa3_write(struct file *file, const char __user *buf,
if (result) {
IPAERR("FW loading process has failed\n");
return result;
- } else
- ipa3_post_init(&ipa3_res, ipa3_ctx->dev);
+ } else {
+ queue_work(ipa3_ctx->transport_power_mgmt_wq,
+ &ipa3_post_init_work);
+ }
}
return count;
}
@@ -4669,20 +4657,6 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
goto fail_device_create;
}
- cdev_init(&ipa3_ctx->cdev, &ipa3_drv_fops);
- ipa3_ctx->cdev.owner = THIS_MODULE;
- ipa3_ctx->cdev.ops = &ipa3_drv_fops; /* from LDD3 */
-
- result = cdev_add(&ipa3_ctx->cdev, ipa3_ctx->dev_num, 1);
- if (result) {
- IPAERR(":cdev_add err=%d\n", -result);
- result = -ENODEV;
- goto fail_cdev_add;
- }
- IPADBG("ipa cdev added successful. major:%d minor:%d\n",
- MAJOR(ipa3_ctx->dev_num),
- MINOR(ipa3_ctx->dev_num));
-
if (ipa3_create_nat_device()) {
IPAERR("unable to create nat device\n");
result = -ENODEV;
@@ -4742,21 +4716,45 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
goto fail_ipa_init_interrupts;
}
}
+ } else {
+ /*
+ * For BAM (No other mode),
+ * we can just carry on with initialization
+ */
+ result = ipa3_post_init(resource_p, ipa_dev);
+ if (result) {
+ IPAERR("ipa3_post_init failed\n");
+ goto fail_ipa_post_init;
+ }
}
- /* For BAM (No other mode), we can just carry on with initialization */
- else
- return ipa3_post_init(resource_p, ipa_dev);
+ cdev_init(&ipa3_ctx->cdev, &ipa3_drv_fops);
+ ipa3_ctx->cdev.owner = THIS_MODULE;
+ ipa3_ctx->cdev.ops = &ipa3_drv_fops; /* from LDD3 */
+
+ result = cdev_add(&ipa3_ctx->cdev, ipa3_ctx->dev_num, 1);
+ if (result) {
+ IPAERR(":cdev_add err=%d\n", -result);
+ result = -ENODEV;
+ goto fail_cdev_add;
+ }
+ IPADBG("ipa cdev added successful. major:%d minor:%d\n",
+ MAJOR(ipa3_ctx->dev_num),
+ MINOR(ipa3_ctx->dev_num));
return 0;
+fail_cdev_add:
+fail_ipa_post_init:
+ if (ipa3_bus_scale_table) {
+ msm_bus_cl_clear_pdata(ipa3_bus_scale_table);
+ ipa3_bus_scale_table = NULL;
+ }
fail_ipa_init_interrupts:
ipa_rm_delete_resource(IPA_RM_RESOURCE_APPS_CONS);
fail_create_apps_resource:
ipa_rm_exit();
fail_ipa_rm_init:
fail_nat_dev_add:
- cdev_del(&ipa3_ctx->cdev);
-fail_cdev_add:
device_destroy(ipa3_ctx->class, ipa3_ctx->dev_num);
fail_device_create:
unregister_chrdev_region(ipa3_ctx->dev_num, 1);
@@ -4798,7 +4796,8 @@ fail_remap:
ipa3_active_clients_log_destroy();
fail_init_active_client:
fail_clk:
- msm_bus_scale_unregister_client(ipa3_ctx->ipa_bus_hdl);
+ if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL)
+ msm_bus_scale_unregister_client(ipa3_ctx->ipa_bus_hdl);
fail_bus_reg:
fail_init_mem_partition:
fail_bind: