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

Commit 7dc85150 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "input: touchscreen: synaptics: fix deadlock"

parents 74c03235 f5901578
Loading
Loading
Loading
Loading
+97 −41
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@

/* #define RESUME_EARLY_UNBLANK */

#define RESET_ON_RESUME_DELAY_MS 20
#define RESET_ON_RESUME_DELAY_MS 50

#define PREDICTIVE_READING

@@ -48,7 +48,7 @@

#define KEEP_DRIVER_ON_ERROR

#define FORCE_RUN_APPLICATION_FIRMWARE
/* #define FORCE_RUN_APPLICATION_FIRMWARE */

#define NOTIFIER_PRIORITY 2

@@ -518,6 +518,7 @@ static void syna_tcm_module_work(struct work_struct *work)
	struct syna_tcm_hcd *tcm_hcd = mod_pool.tcm_hcd;

	mutex_lock(&mod_pool.mutex);
	mod_pool.reconstructing = true;

	if (!list_empty(&mod_pool.list)) {
		list_for_each_entry_safe(mod_handler,
@@ -538,6 +539,7 @@ static void syna_tcm_module_work(struct work_struct *work)
		}
	}

	mod_pool.reconstructing = false;
	mutex_unlock(&mod_pool.mutex);
}

@@ -568,6 +570,7 @@ static int syna_tcm_report_notifier(void *data)
		set_current_state(TASK_RUNNING);

		mutex_lock(&mod_pool.mutex);
		mod_pool.reconstructing = true;

		if (!list_empty(&mod_pool.list)) {
			list_for_each_entry(mod_handler, &mod_pool.list, link) {
@@ -578,6 +581,7 @@ static int syna_tcm_report_notifier(void *data)
			}
		}

		mod_pool.reconstructing = false;
		mutex_unlock(&mod_pool.mutex);

		set_current_state(TASK_INTERRUPTIBLE);
@@ -780,10 +784,15 @@ static void syna_tcm_dispatch_message(struct syna_tcm_hcd *tcm_hcd)
#endif
	}

	if (tcm_hcd->status_report_code >= REPORT_IDENTIFY)
	if (tcm_hcd->status_report_code >= REPORT_IDENTIFY) {
		if ((mod_pool.reconstructing)
			&& (tcm_hcd->status_report_code == REPORT_TOUCH))
			return;
		syna_tcm_dispatch_report(tcm_hcd);
	else

	} else
		syna_tcm_dispatch_response(tcm_hcd);

}

/**
@@ -1291,10 +1300,14 @@ static int syna_tcm_read_message(struct syna_tcm_hcd *tcm_hcd,
		tcm_hcd->read_length = total_length;
#endif

	mutex_unlock(&tcm_hcd->rw_ctrl_mutex);

	syna_tcm_dispatch_message(tcm_hcd);

	retval = 0;

	return retval;

exit:
	if (retval < 0) {
		if (atomic_read(&tcm_hcd->command_status) == CMD_BUSY) {
@@ -2703,6 +2716,7 @@ static int syna_tcm_reset(struct syna_tcm_hcd *tcm_hcd, bool hw, bool update_wd)

dispatch_reset:
	mutex_lock(&mod_pool.mutex);
	mod_pool.reconstructing = true;

	if (!list_empty(&mod_pool.list)) {
		list_for_each_entry(mod_handler, &mod_pool.list, link) {
@@ -2713,6 +2727,7 @@ static int syna_tcm_reset(struct syna_tcm_hcd *tcm_hcd, bool hw, bool update_wd)
		}
	}

	mod_pool.reconstructing = false;
	mutex_unlock(&mod_pool.mutex);

	retval = 0;
@@ -3004,8 +3019,24 @@ static int syna_tcm_fb_notifier_cb(struct notifier_block *nb,
	if (!evdata || (evdata->id != 0))
		return 0;

	if (evdata && evdata->data && tcm_hcd) {
	if (!evdata->data || !tcm_hcd)
		return 0;

	transition = (int *) evdata->data;

	if (atomic_read(&tcm_hcd->firmware_flashing)
		&& *transition == MSM_DRM_BLANK_POWERDOWN) {
		retval = wait_event_interruptible_timeout(tcm_hcd->reflash_wq,
				!atomic_read(&tcm_hcd->firmware_flashing),
				msecs_to_jiffies(RESPONSE_TIMEOUT_MS));
		if (retval == 0) {
			LOGE(tcm_hcd->pdev->dev.parent,
				"Timed out waiting for flashing firmware\n");
			atomic_set(&tcm_hcd->firmware_flashing, 0);
			return -EIO;
		}
	}

	if (action == MSM_DRM_EARLY_EVENT_BLANK &&
			*transition == MSM_DRM_BLANK_POWERDOWN)
		retval = syna_tcm_early_suspend(&tcm_hcd->pdev->dev);
@@ -3026,7 +3057,7 @@ static int syna_tcm_fb_notifier_cb(struct notifier_block *nb,
		tcm_hcd->fb_ready++;
#endif
	}
	}


	return 0;
}
@@ -3082,16 +3113,30 @@ static int syna_tcm_early_suspend(struct device *dev)
static int syna_tcm_fb_notifier_cb(struct notifier_block *nb,
		unsigned long action, void *data)
{
	int retval;
	int retval = 0;
	int *transition;
	struct fb_event *evdata = data;
	struct syna_tcm_hcd *tcm_hcd =
			container_of(nb, struct syna_tcm_hcd, fb_notifier);

	retval = 0;
	if (!evdata || !evdata->data || !tcm_hcd)
		return 0;

	if (evdata && evdata->data && tcm_hcd) {
	transition = (int *)evdata->data;

	if (atomic_read(&tcm_hcd->firmware_flashing)
		&& *transition == FB_BLANK_POWERDOWN) {
		retval = wait_event_interruptible_timeout(tcm_hcd->reflash_wq,
				!atomic_read(&tcm_hcd->firmware_flashing),
				msecs_to_jiffies(RESPONSE_TIMEOUT_MS));
		if (retval == 0) {
			LOGE(tcm_hcd->pdev->dev.parent,
				"Timed out waiting for flashing firmware\n");
			atomic_set(&tcm_hcd->firmware_flashing, 0);
			return -EIO;
		}
	}

	if (action == FB_EARLY_EVENT_BLANK &&
			*transition == FB_BLANK_POWERDOWN)
		retval = syna_tcm_early_suspend(&tcm_hcd->pdev->dev);
@@ -3112,7 +3157,6 @@ static int syna_tcm_fb_notifier_cb(struct notifier_block *nb,
		tcm_hcd->fb_ready++;
#endif
	}
	}

	return 0;
}
@@ -3216,6 +3260,9 @@ static int syna_tcm_probe(struct platform_device *pdev)

	init_waitqueue_head(&tcm_hcd->hdl_wq);

	init_waitqueue_head(&tcm_hcd->reflash_wq);
	atomic_set(&tcm_hcd->firmware_flashing, 0);

	if (!mod_pool.initialized) {
		mutex_init(&mod_pool.mutex);
		INIT_LIST_HEAD(&mod_pool.list);
@@ -3326,6 +3373,7 @@ static int syna_tcm_probe(struct platform_device *pdev)
	INIT_WORK(&mod_pool.work, syna_tcm_module_work);
	mod_pool.tcm_hcd = tcm_hcd;
	mod_pool.queue_work = true;
	mod_pool.reconstructing = false;

	return 0;

@@ -3428,13 +3476,15 @@ static int syna_tcm_remove(struct platform_device *pdev)
{
	int idx;
	struct syna_tcm_module_handler *mod_handler;
	struct syna_tcm_module_handler *tmp_handler;
	struct syna_tcm_hcd *tcm_hcd = platform_get_drvdata(pdev);
	const struct syna_tcm_board_data *bdata = tcm_hcd->hw_if->bdata;

	mutex_lock(&mod_pool.mutex);

	if (!list_empty(&mod_pool.list)) {
		list_for_each_entry(mod_handler, &mod_pool.list, link) {
		list_for_each_entry_safe(mod_handler, tmp_handler,
				&mod_pool.list, link) {
			if (mod_handler->mod_cb->remove)
				mod_handler->mod_cb->remove(tcm_hcd);
			list_del(&mod_handler->link);
@@ -3513,6 +3563,11 @@ static int syna_tcm_remove(struct platform_device *pdev)
	return 0;
}

static void syna_tcm_shutdown(struct platform_device *pdev)
{
	syna_tcm_remove(pdev);
}

#ifdef CONFIG_PM
static const struct dev_pm_ops syna_tcm_dev_pm_ops = {
#if !defined(CONFIG_DRM) && !defined(CONFIG_FB)
@@ -3532,6 +3587,7 @@ static struct platform_driver syna_tcm_driver = {
	},
	.probe = syna_tcm_probe,
	.remove = syna_tcm_remove,
	.shutdown = syna_tcm_shutdown,
};

static int __init syna_tcm_module_init(void)
+3 −0
Original line number Diff line number Diff line
@@ -387,7 +387,9 @@ struct syna_tcm_hcd {
	pid_t isr_pid;
	atomic_t command_status;
	atomic_t host_downloading;
	atomic_t firmware_flashing;
	wait_queue_head_t hdl_wq;
	wait_queue_head_t reflash_wq;
	int irq;
	bool init_okay;
	bool do_polling;
@@ -487,6 +489,7 @@ struct syna_tcm_module_handler {
struct syna_tcm_module_pool {
	bool initialized;
	bool queue_work;
	bool reconstructing;
	struct mutex mutex;
	struct list_head list;
	struct work_struct work;
+5 −2
Original line number Diff line number Diff line
@@ -257,10 +257,13 @@ static int device_ioctl(struct inode *inp, struct file *filp, unsigned int cmd,
			retval = tcm_hcd->enable_irq(tcm_hcd, true, NULL);
		break;
	case DEVICE_IOC_RAW:
		if (arg == 0)
		if (arg == 0) {
			device_hcd->raw_mode = false;
		else if (arg == 1)
			tcm_hcd->update_watchdog(tcm_hcd, true);
		} else if (arg == 1) {
			device_hcd->raw_mode = true;
			tcm_hcd->update_watchdog(tcm_hcd, false);
		}
		break;
	case DEVICE_IOC_CONCURRENT:
		if (arg == 0)
+4 −0
Original line number Diff line number Diff line
@@ -1877,6 +1877,8 @@ static int reflash_do_reflash(void)
	LOGN(tcm_hcd->pdev->dev.parent,
			"Start of reflash\n");

	atomic_set(&tcm_hcd->firmware_flashing, 1);

	update_area = reflash_compare_id_info();

	switch (update_area) {
@@ -1930,6 +1932,8 @@ static int reflash_do_reflash(void)
		reflash_hcd->image_size = 0;
	}

	atomic_set(&tcm_hcd->firmware_flashing, 0);
	wake_up_interruptible(&tcm_hcd->reflash_wq);
	return retval;
}

+8 −1
Original line number Diff line number Diff line
@@ -1070,6 +1070,7 @@ static int touch_remove(struct syna_tcm_hcd *tcm_hcd)

	tcm_hcd->report_touch = NULL;

	if (touch_hcd->input_dev)
		input_unregister_device(touch_hcd->input_dev);

	kfree(touch_hcd->touch_data.object_data);
@@ -1164,7 +1165,11 @@ static int touch_early_suspend(struct syna_tcm_hcd *tcm_hcd)
	if (!touch_hcd)
		return 0;

#ifdef WAKEUP_GESTURE
	touch_hcd->suspend_touch = false;
#else
	touch_hcd->suspend_touch = true;
#endif

	touch_free_objects();

@@ -1190,6 +1195,8 @@ static int touch_suspend(struct syna_tcm_hcd *tcm_hcd)
		touch_hcd->irq_wake = true;
	}

	touch_hcd->suspend_touch = false;

	retval = tcm_hcd->set_dynamic_config(tcm_hcd,
			DC_IN_WAKEUP_GESTURE_MODE,
			1);