From 64a7b2e649b19e747fa805079c203f1d8753a81d Mon Sep 17 00:00:00 2001 From: Ram Chandrasekar Date: Wed, 23 Nov 2016 14:21:47 -0700 Subject: [PATCH 1/2] msm: lmh_dcvsh: Support new API to notify scheduler HLOS can place a mitigation frequency via the LMH DCVSh hardware using the software cap register and this request doesn't trigger a debug interrupt. Thus, this frequency mitigation change will not result in scheduler being notified by LMH DCVSh driver. Introduce a new API in LMH DCVSh driver, that can be used by other drivers to trigger the scheduler notification. This API and the interrupt handler follows the same code path to poll and notify the scheduler. Change-Id: Iefcdb57ff598ecb1bafc535958684f75b1f6e645 Signed-off-by: Ram Chandrasekar --- drivers/thermal/msm_lmh_dcvs.c | 32 +++++++++++++++++++++++++++----- include/linux/msm_thermal.h | 13 +++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/msm_lmh_dcvs.c b/drivers/thermal/msm_lmh_dcvs.c index 3758e39a1c02..ac1da854ab32 100644 --- a/drivers/thermal/msm_lmh_dcvs.c +++ b/drivers/thermal/msm_lmh_dcvs.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -83,6 +85,7 @@ struct msm_lmh_dcvs_hw { uint32_t max_freq; uint32_t hw_freq_limit; struct list_head list; + DECLARE_BITMAP(is_irq_enabled, 1); }; LIST_HEAD(lmh_dcvs_hw_list); @@ -145,6 +148,7 @@ static void msm_lmh_dcvs_poll(unsigned long data) if (max_limit >= hw->max_freq) { del_timer(&hw->poll_timer); writel_relaxed(0xFF, hw->int_clr_reg); + set_bit(1, hw->is_irq_enabled); enable_irq(hw->irq_num); } else { mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( @@ -152,15 +156,21 @@ static void msm_lmh_dcvs_poll(unsigned long data) } } +static void lmh_dcvs_notify(struct msm_lmh_dcvs_hw *hw) +{ + if (test_and_clear_bit(1, hw->is_irq_enabled)) { + disable_irq_nosync(hw->irq_num); + msm_lmh_mitigation_notify(hw); + mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( + MSM_LIMITS_POLLING_DELAY_MS)); + } +} + static irqreturn_t lmh_dcvs_handle_isr(int irq, void *data) { struct msm_lmh_dcvs_hw *hw = data; - disable_irq_nosync(irq); - msm_lmh_mitigation_notify(hw); - mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( - MSM_LIMITS_POLLING_DELAY_MS)); - + lmh_dcvs_notify(hw); return IRQ_HANDLED; } @@ -314,6 +324,17 @@ static struct cpu_cooling_ops cd_ops = { .ceil_limit = lmh_set_max_limit, }; +int msm_lmh_dcvsh_sw_notify(int cpu) +{ + struct msm_lmh_dcvs_hw *hw = get_dcvsh_hw_from_cpu(cpu); + + if (!hw) + return -EINVAL; + + lmh_dcvs_notify(hw); + return 0; +} + static int msm_lmh_dcvs_probe(struct platform_device *pdev) { int ret; @@ -460,6 +481,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev) pr_err("Error getting IRQ number. err:%d\n", ret); return ret; } + set_bit(1, hw->is_irq_enabled); ret = devm_request_threaded_irq(&pdev->dev, hw->irq_num, NULL, lmh_dcvs_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_SUSPEND, sensor_name, hw); diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h index f3ec960536aa..33286c2d81fc 100644 --- a/include/linux/msm_thermal.h +++ b/include/linux/msm_thermal.h @@ -255,6 +255,15 @@ extern int devmgr_client_request_mitigation(struct device_clnt_data *clnt, extern void devmgr_unregister_mitigation_client( struct device *dev, struct device_clnt_data *clnt); +#ifdef CONFIG_QCOM_THERMAL_LIMITS_DCVS +extern int msm_lmh_dcvsh_sw_notify(int cpu); +#else +static inline int msm_lmh_dcvsh_sw_notify(int cpu) +{ + return -ENODEV; +} +#endif + #else static inline int msm_thermal_init(struct msm_thermal_data *pdata) { @@ -330,6 +339,10 @@ static inline void devmgr_unregister_mitigation_client( struct device_clnt_data *clnt) { } +static inline int msm_lmh_dcvsh_sw_notify(int cpu) +{ + return -ENODEV; +} #endif #endif /*__MSM_THERMAL_H*/ From e219034e0473f7cade281d7e59d9cc6418040884 Mon Sep 17 00:00:00 2001 From: Ram Chandrasekar Date: Wed, 23 Nov 2016 14:39:13 -0700 Subject: [PATCH 2/2] msm: thermal: Notify LMH DCVSh driver after freq mitigation request LMH DCVSh hardware doesn't generate a debug interrupt, when HLOS CPU frequency cap is the only throttling value coming to the hardware aggregator logic. The LMH DCVSh requires atleast one of the hardware algorithm to throttle to generate a debug interrupt. So there will be a case where, LMH DCVS driver won't notify scheduler about the throttling frequency if HLOS is the only reason for throttling. LMH DCVSh driver now exposes a new API, to trigger the frequency polling loop. KTM is updated to use this API to trigger the LMH DCVSh polling, whenever there is a new software frequency cap. This will ensure that the LMH DCVSh will notify the scheduler even if software is the only throttling reason. Change-Id: I92b1bd9a5efc9810eea721b088dff1bd6eef3838 Signed-off-by: Ram Chandrasekar --- drivers/thermal/msm_thermal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c index 002cafb08f37..7158fb1239df 100644 --- a/drivers/thermal/msm_thermal.c +++ b/drivers/thermal/msm_thermal.c @@ -1056,6 +1056,11 @@ static int msm_lmh_dcvs_update(int cpu) MSM_LIMITS_DOMAIN_MIN, min_freq); if (ret) return ret; + /* + * Notify LMH dcvs driver about the new software limit. This will + * trigger LMH DCVS driver polling for the mitigated frequency. + */ + msm_lmh_dcvsh_sw_notify(cpu); return ret; }