From 2a75fc5624ecc483ed5e4b6e2c5423fc5d4b1495 Mon Sep 17 00:00:00 2001 From: Melody Olvera Date: Fri, 2 Oct 2020 09:13:10 -0700 Subject: [PATCH] Revert "soc: qcom: Remove watchdog percpu interrupts" This reverts commit d71acda6dcba348e00523949ddea1eb7ebbd9da1. This is being reverted because sdxlemur uses percpu interrupts in its watchdog. This change also adds back in fields used by this code and fixes issues introduced by new code. Change-Id: Ic5ddbebd6c6f4b4c5d157a86a3ecd827e1b5376f Signed-off-by: Melody Olvera --- drivers/soc/qcom/qcom_wdt_core.c | 71 +++++++++++++++++++++++++++----- include/soc/qcom/watchdog.h | 2 + 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/drivers/soc/qcom/qcom_wdt_core.c b/drivers/soc/qcom/qcom_wdt_core.c index a50b18e30cab..7f464a604fbd 100644 --- a/drivers/soc/qcom/qcom_wdt_core.c +++ b/drivers/soc/qcom/qcom_wdt_core.c @@ -10,6 +10,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -458,7 +463,15 @@ static void qcom_wdt_unregister_die_notifier(struct msm_watchdog_data *wdog_dd) static void qcom_wdt_disable(struct msm_watchdog_data *wdog_dd) { wdog_dd->ops->disable_wdt(wdog_dd); - devm_free_irq(wdog_dd->dev, wdog_dd->bark_irq, wdog_dd); + + if (wdog_dd->irq_ppi) { + disable_percpu_irq(wdog_dd->bark_irq); + free_percpu_irq(wdog_dd->bark_irq, + (void __percpu *)wdog_dd->wdog_cpu_dd); + } else { + devm_free_irq(wdog_dd->dev, wdog_dd->bark_irq, wdog_dd); + } + wdog_dd->enabled = false; /*Ensure all cpus see update to enable*/ smp_mb(); @@ -733,6 +746,8 @@ int qcom_wdt_remove(struct platform_device *pdev) mutex_unlock(&wdog_dd->disable_lock); device_remove_file(wdog_dd->dev, &dev_attr_disable); + if (wdog_dd->irq_ppi) + free_percpu((void __percpu *)wdog_dd->wdog_cpu_dd); 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); @@ -798,6 +813,14 @@ static irqreturn_t qcom_wdt_bark_handler(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t qcom_wdt_ppi_bark(int irq, void *dev_id_percpu) +{ + void *dev_id = raw_cpu_ptr((void __percpu *)dev_id_percpu); + struct msm_watchdog_data *wdog_dd = *((struct msm_watchdog_data **)dev_id); + + return qcom_wdt_bark_handler(irq, wdog_dd); +} + static int qcom_wdt_init_sysfs(struct msm_watchdog_data *wdog_dd) { int error = 0; @@ -820,17 +843,35 @@ static int qcom_wdt_init(struct msm_watchdog_data *wdog_dd, unsigned long delay_time; uint32_t val; int ret; + void *wdog_cpu_dd_v; - ret = devm_request_irq(wdog_dd->dev, wdog_dd->bark_irq, - qcom_wdt_bark_handler, - IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, - "apps_wdog_bark", wdog_dd); - if (ret) { - dev_err(wdog_dd->dev, "failed to request bark irq\n"); - return -EINVAL; + if (wdog_dd->irq_ppi) { + wdog_dd->wdog_cpu_dd = alloc_percpu(struct msm_watchdog_data *); + if (!wdog_dd->wdog_cpu_dd) { + dev_err(wdog_dd->dev, "failed to allocate cpu data\n"); + return -ENOMEM; + } + wdog_cpu_dd_v = raw_cpu_ptr((void __percpu *)wdog_dd->wdog_cpu_dd); + *((struct msm_watchdog_data **)wdog_cpu_dd_v) = wdog_dd; + ret = request_percpu_irq(wdog_dd->bark_irq, qcom_wdt_ppi_bark, + "apps_wdog_bark", + (void __percpu *)wdog_dd->wdog_cpu_dd); + if (ret) { + dev_err(wdog_dd->dev, "failed to request bark irq\n"); + free_percpu((void __percpu *)wdog_dd->wdog_cpu_dd); + return ret; + } + } else { + ret = devm_request_irq(wdog_dd->dev, wdog_dd->bark_irq, + qcom_wdt_bark_handler, + IRQF_TRIGGER_RISING, + "apps_wdog_bark", wdog_dd); + if (ret) { + dev_err(wdog_dd->dev, "failed to request bark irq: %d\n", ret); + return -EINVAL; + } } - INIT_WORK(&wdog_dd->irq_counts_work, compute_irq_stat); - atomic_set(&wdog_dd->irq_counts_running, 0); + delay_time = msecs_to_jiffies(wdog_dd->pet_time); wdog_dd->ops->set_bark_time(wdog_dd->bark_time, wdog_dd); wdog_dd->ops->set_bite_time(wdog_dd->bark_time + 3 * 1000, wdog_dd); @@ -863,6 +904,13 @@ static int qcom_wdt_init(struct msm_watchdog_data *wdog_dd, &wdog_dd->panic_blk); qcom_wdt_unregister_die_notifier(wdog_dd); unregister_restart_handler(&wdog_dd->restart_blk); + + if (wdog_dd->irq_ppi) { + free_percpu_irq(wdog_dd->bark_irq, + (void __percpu *)wdog_dd->wdog_cpu_dd); + free_percpu((void __percpu *)wdog_dd->wdog_cpu_dd); + } + del_timer_sync(&wdog_dd->pet_timer); flush_work(&wdog_dd->irq_counts_work); dev_err(wdog_dd->dev, "Failed Initializing QCOM Apps Watchdog\n"); @@ -875,6 +923,8 @@ static int qcom_wdt_init(struct msm_watchdog_data *wdog_dd, qcom_wdt_init_sysfs(wdog_dd); + if (wdog_dd->irq_ppi) + enable_percpu_irq(wdog_dd->bark_irq, 0); if (!IPI_CORES_IN_LPM) { wdog_dd->wdog_cpu_pm_nb.notifier_call = qcom_wdt_cpu_pm_notify; cpu_pm_register_notifier(&wdog_dd->wdog_cpu_pm_nb); @@ -897,6 +947,7 @@ static void qcom_wdt_dt_to_pdata(struct platform_device *pdev, struct msm_watchdog_data *pdata) { pdata->bark_irq = platform_get_irq(pdev, 0); + pdata->irq_ppi = irq_is_percpu(pdata->bark_irq); pdata->bark_time = QCOM_WATCHDOG_BARK_TIME; pdata->pet_time = QCOM_WATCHDOG_PET_TIME; pdata->do_ipi_ping = QCOM_WATCHDOG_IPI_PING; diff --git a/include/soc/qcom/watchdog.h b/include/soc/qcom/watchdog.h index 8e84b489f9cd..f7a7dacb3a93 100644 --- a/include/soc/qcom/watchdog.h +++ b/include/soc/qcom/watchdog.h @@ -118,9 +118,11 @@ struct msm_watchdog_data { 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;