Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ded7814c authored by Utkarsh Saxena's avatar Utkarsh Saxena Committed by Utkarsh Saxena
Browse files

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: default avatarMohammed Javid <mjavid@qti.qualcomm.com>
Signed-off-by: default avatarUtkarsh Saxena <usaxena@codeaurora.org>
parent 5915565f
Loading
Loading
Loading
Loading
+35 −50
Original line number Diff line number Diff line
@@ -232,6 +232,9 @@ static DECLARE_DELAYED_WORK(ipa3_transport_release_resource_work,
	ipa3_transport_release_resource);
static void ipa_gsi_notify_cb(struct gsi_per_notify *notify);

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;

@@ -3979,6 +3982,15 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
	struct ipa3_flt_tbl *flt_tbl;
	int i;

	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;

	/*
	 * indication whether working in MHI config or non MHI config is given
	 * in ipa3_write which is launched before ipa3_post_init. i.e. from
@@ -4113,41 +4125,15 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
fail_setup_apps_pipes:
	gsi_deregister_device(ipa3_ctx->gsi_dev_hdl, false);
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);
	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();
	if (ipa3_clk)
		clk_put(ipa3_clk);
	ipa3_clk = NULL;
	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;
@@ -4249,9 +4235,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;
}

@@ -4722,20 +4709,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;
@@ -4793,16 +4766,28 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		}
	}

	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_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);