diff options
author | Utkarsh Saxena <usaxena@codeaurora.org> | 2017-05-03 14:04:30 +0530 |
---|---|---|
committer | Utkarsh Saxena <usaxena@codeaurora.org> | 2017-05-18 16:09:00 +0530 |
commit | 2931599ee9a0a58e2878a6d1757c1d32c5e11294 (patch) | |
tree | 52db74b38516d2432efad16ed61c31d275996c5d /drivers/platform | |
parent | c01ba1a5f98de6e2f271cc2e447fe3280920cc16 (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.c | 105 |
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: |