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

Commit 64fdb4fa authored by Maria Yu's avatar Maria Yu Committed by Gerrit - the friendly Code Review server
Browse files

soc: wdog: Ensure missing user watchdog pet can trigger bite



The user watchdog was waiting the hardware watchdog bite by
stop petting it. But in the cpu suspend scenarios, the auto petting
by hardware prevent the expected watchdog bite. So add a new user pet
timer to explicitly trigger the watchdog bite by software when the user
watchdog petting is not happenned before timeout.

Change-Id: I71b1139192baa960ae00f7a27c630aedaf5a3ffa
Signed-off-by: default avatarMaria Yu <aiquny@codeaurora.org>
parent 9585c2cb
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -371,6 +371,8 @@ int qcom_wdt_pet_suspend(struct device *dev)
	wdog_dd->freeze_in_progress = true;
	spin_unlock(&wdog_dd->freeze_lock);
	del_timer_sync(&wdog_dd->pet_timer);
	if (wdog_dd->user_pet_enabled)
		del_timer_sync(&wdog_dd->user_pet_timer);
	return 0;
}
EXPORT_SYMBOL(qcom_wdt_pet_suspend);
@@ -390,6 +392,11 @@ int qcom_wdt_pet_resume(struct device *dev)
	spin_lock(&wdog_dd->freeze_lock);
	wdog_dd->pet_timer.expires = jiffies + delay_time;
	add_timer(&wdog_dd->pet_timer);
	if (wdog_dd->user_pet_enabled) {
		delay_time = msecs_to_jiffies(wdog_dd->bark_time + 3 * 1000);
		wdog_dd->user_pet_timer.expires = jiffies + delay_time;
		add_timer(&wdog_dd->user_pet_timer);
	}
	wdog_dd->freeze_in_progress = false;
	spin_unlock(&wdog_dd->freeze_lock);
	return 0;
@@ -480,6 +487,8 @@ static void qcom_wdt_disable(struct msm_watchdog_data *wdog_dd)
	qcom_wdt_unregister_die_notifier(wdog_dd);
	unregister_restart_handler(&wdog_dd->restart_blk);
	del_timer_sync(&wdog_dd->pet_timer);
	if (wdog_dd->user_pet_enabled)
		del_timer_sync(&wdog_dd->user_pet_timer);
	wdog_dd->ops->disable_wdt(wdog_dd);
	dev_err(wdog_dd->dev, "QCOM Apps Watchdog deactivated\n");
}
@@ -583,6 +592,8 @@ static ssize_t qcom_wdt_user_pet_enabled_set(struct device *dev,
{
	struct msm_watchdog_data *wdog_dd = dev_get_drvdata(dev);
	int ret;
	unsigned long delay_time = 0;
	bool already_enabled = wdog_dd->user_pet_enabled;

	ret = strtobool(buf, &wdog_dd->user_pet_enabled);
	if (ret) {
@@ -590,6 +601,12 @@ static ssize_t qcom_wdt_user_pet_enabled_set(struct device *dev,
		return ret;
	}

	delay_time = msecs_to_jiffies(wdog_dd->bark_time + 3 * 1000);
	if (wdog_dd->user_pet_enabled)
		mod_timer(&wdog_dd->user_pet_timer, jiffies + delay_time);
	else if (already_enabled)
		del_timer_sync(&wdog_dd->user_pet_timer);

	__qcom_wdt_user_pet(wdog_dd);

	return count;
@@ -650,6 +667,15 @@ static void qcom_wdt_pet_task_wakeup(struct timer_list *t)
	wdog_dd->timer_fired = sched_clock();
	wake_up(&wdog_dd->pet_complete);
}
static void qcom_wdt_user_pet_bite(struct timer_list *t)
{
	struct msm_watchdog_data *wdog_dd =
		from_timer(wdog_dd, t, user_pet_timer);
	if (!wdog_dd->user_pet_complete) {
		dev_info(wdog_dd->dev, "QCOM Apps Watchdog user pet timeout!\n");
		qcom_wdt_trigger_bite();
	}
}

static __ref int qcom_wdt_kthread(void *arg)
{
@@ -751,6 +777,8 @@ int qcom_wdt_remove(struct platform_device *pdev)
	irq_dispose_mapping(wdog_dd->bark_irq);
	dev_info(wdog_dd->dev, "QCOM Apps Watchdog Exit - Deactivated\n");
	del_timer_sync(&wdog_dd->pet_timer);
	if (wdog_dd->user_pet_enabled)
		del_timer_sync(&wdog_dd->user_pet_timer);
	wdog_dd->timer_expired = true;
	wdog_dd->user_pet_complete = true;
	kthread_stop(wdog_dd->watchdog_task);
@@ -895,6 +923,7 @@ static int qcom_wdt_init(struct msm_watchdog_data *wdog_dd,
	timer_setup(&wdog_dd->pet_timer, qcom_wdt_pet_task_wakeup, 0);
	wdog_dd->pet_timer.expires = jiffies + delay_time;
	add_timer(&wdog_dd->pet_timer);
	timer_setup(&wdog_dd->user_pet_timer, qcom_wdt_user_pet_bite, 0);
	val = BIT(EN);
	if (wdog_dd->wakeup_irq_enable)
		val |= BIT(UNMASKED_INT_EN);
+1 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ struct msm_watchdog_data {
	struct qcom_irq_info ipi_counts[NR_IPI];
	unsigned int tot_irq_count[NR_CPUS];
	atomic_t irq_counts_running;
	struct timer_list user_pet_timer;
};

extern void qcom_wdt_trigger_bite(void);