android_kernel_xiaomi_sm8350/include/soc/qcom/watchdog.h
Maria Yu 64fdb4fa1d 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: Maria Yu <aiquny@codeaurora.org>
2021-07-01 05:55:35 -07:00

167 lines
4.5 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
*/
#ifndef _SOC_QCOM_WATCHDOG_H_
#define _SOC_QCOM_WATCHDOG_H_
#ifdef CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC
#define WDOG_BITE_ON_PANIC 1
#else
#define WDOG_BITE_ON_PANIC 0
#endif
#ifdef CONFIG_QCOM_WDOG_BITE_EARLY_PANIC
#define WDOG_BITE_EARLY_PANIC 1
#else
#define WDOG_BITE_EARLY_PANIC 0
#endif
/*
* Watchdog ipi optimization:
* Does not ping cores in low power mode at pet time to save power.
* This feature is enabled by default.
*
* Can be turned off, by enabling CONFIG_QCOM_WDOG_IPI_ENABLE.
*/
#ifdef CONFIG_QCOM_WDOG_IPI_ENABLE
#define IPI_CORES_IN_LPM 1
#else
#define IPI_CORES_IN_LPM 0
#endif
#if IS_ENABLED(CONFIG_QCOM_WDT_CORE)
#include <linux/platform_device.h>
#include <asm/hardirq.h>
/**
* The enable constant that can be used between the core framework and the
* watchdog driver.
*/
#define EN 0
#define UNMASKED_INT_EN 1
/* Watchdog property values */
#define QCOM_WATCHDOG_BARK_TIME CONFIG_QCOM_WATCHDOG_BARK_TIME
#define QCOM_WATCHDOG_PET_TIME CONFIG_QCOM_WATCHDOG_PET_TIME
#ifdef CONFIG_QCOM_WATCHDOG_IPI_PING
#define QCOM_WATCHDOG_IPI_PING 1
#else
#define QCOM_WATCHDOG_IPI_PING 0
#endif
#ifdef CONFIG_QCOM_WATCHDOG_WAKEUP_ENABLE
#define QCOM_WATCHDOG_WAKEUP_ENABLE 1
#else
#define QCOM_WATCHDOG_WAKEUP_ENABLE 0
#endif
#ifdef CONFIG_QCOM_WATCHDOG_USERSPACE_PET
#define QCOM_WATCHDOG_USERSPACE_PET 1
#else
#define QCOM_WATCHDOG_USERSPACE_PET 0
#endif
#define NR_TOP_HITTERS 10
struct qcom_wdt_ops;
struct msm_watchdog_data;
/** qcom_irq_info - IRQ stats
*
* @irq: linux/virtual irq numer.
* @total_count: sum of irq occurrence count on all cpu's.
* @irq_counter: irq occurrence count on each cpu.
*/
struct qcom_irq_info {
unsigned int irq;
unsigned int total_count;
unsigned int irq_counter[NR_CPUS];
};
/** qcom_wdt_ops - The msm-watchdog-devices operations
*
* @set_bark_time: The routine for setting the watchdog bark time.
* @set_bite_time: The routine for setting the watchdog bite time.
* @reset_wdt: The routine for resetting the watchdog timer.
* @enable_wdt: The routine for enabling the watchdog.
* @disable_wdt: The routine for disabling the watchdog.
* @show_wdt_status: The routine that shows the status of the watchdog.
*
* The qcom_wdt_ops structure contains a list of operations that are
* used to control the watchdog.
*/
struct qcom_wdt_ops {
int (*set_bark_time)(u32 time, struct msm_watchdog_data *wdog_dd);
int (*set_bite_time)(u32 time, struct msm_watchdog_data *wdog_dd);
int (*reset_wdt)(struct msm_watchdog_data *wdog_dd);
int (*enable_wdt)(u32 val, struct msm_watchdog_data *wdog_dd);
int (*disable_wdt)(struct msm_watchdog_data *wdog_dd);
int (*show_wdt_status)(struct msm_watchdog_data *wdog_dd);
};
/*
* user_pet_enable:
* Require userspace to write to a sysfs file every pet_time milliseconds.
* Disabled by default on boot.
*/
struct msm_watchdog_data {
void __iomem *base;
struct device *dev;
struct qcom_wdt_ops *ops;
unsigned int pet_time;
unsigned int bark_time;
unsigned int bark_irq;
bool do_ipi_ping;
bool in_panic;
bool wakeup_irq_enable;
bool irq_ppi;
unsigned long long last_pet;
cpumask_t alive_mask;
struct mutex disable_lock;
struct msm_watchdog_data * __percpu *wdog_cpu_dd;
struct notifier_block panic_blk;
struct notifier_block die_blk;
struct notifier_block wdog_cpu_pm_nb;
struct notifier_block restart_blk;
bool enabled;
bool user_pet_enabled;
struct task_struct *watchdog_task;
struct timer_list pet_timer;
wait_queue_head_t pet_complete;
bool timer_expired;
bool user_pet_complete;
unsigned long long timer_fired;
unsigned long long thread_start;
unsigned long long ping_start[NR_CPUS];
unsigned long long ping_end[NR_CPUS];
int cpu_idle_pc_state[NR_CPUS];
bool freeze_in_progress;
spinlock_t freeze_lock;
struct work_struct irq_counts_work;
struct qcom_irq_info irq_counts[NR_TOP_HITTERS];
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);
int qcom_wdt_register(struct platform_device *pdev,
struct msm_watchdog_data *wdog_dd,
char *wdog_dd_name);
int qcom_wdt_pet_suspend(struct device *dev);
int qcom_wdt_pet_resume(struct device *dev);
int qcom_wdt_remove(struct platform_device *pdev);
#else
static inline void qcom_wdt_trigger_bite(void) { }
#endif
#endif