Loading drivers/thermal/qcom/msm_lmh_dcvs.c +21 −17 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -98,13 +98,13 @@ struct limits_dcvs_hw { void *int_clr_reg; void *min_freq_reg; cpumask_t core_map; struct timer_list poll_timer; struct delayed_work freq_poll_work; unsigned long max_freq; unsigned long min_freq; unsigned long hw_freq_limit; struct device_attribute lmh_freq_attr; struct list_head list; atomic_t is_irq_enabled; bool is_irq_enabled; struct mutex access_lock; struct __limits_cdev_data *cdev_data; struct regulator *isens_reg; Loading Loading @@ -184,33 +184,37 @@ static unsigned long limits_mitigation_notify(struct limits_dcvs_hw *hw) return max_limit; } static void limits_dcvs_poll(unsigned long data) static void limits_dcvs_poll(struct work_struct *work) { unsigned long max_limit = 0; struct limits_dcvs_hw *hw = (struct limits_dcvs_hw *)data; struct limits_dcvs_hw *hw = container_of(work, struct limits_dcvs_hw, freq_poll_work.work); mutex_lock(&hw->access_lock); if (hw->max_freq == UINT_MAX) limits_dcvs_get_freq_limits(cpumask_first(&hw->core_map), &hw->max_freq, &hw->min_freq); max_limit = limits_mitigation_notify(hw); if (max_limit >= hw->max_freq) { del_timer(&hw->poll_timer); writel_relaxed(0xFF, hw->int_clr_reg); atomic_set(&hw->is_irq_enabled, 1); hw->is_irq_enabled = true; enable_irq(hw->irq_num); } else { mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( LIMITS_POLLING_DELAY_MS)); mod_delayed_work(system_highpri_wq, &hw->freq_poll_work, msecs_to_jiffies(LIMITS_POLLING_DELAY_MS)); } mutex_unlock(&hw->access_lock); } static void lmh_dcvs_notify(struct limits_dcvs_hw *hw) { if (atomic_dec_and_test(&hw->is_irq_enabled)) { if (hw->is_irq_enabled) { hw->is_irq_enabled = false; disable_irq_nosync(hw->irq_num); limits_mitigation_notify(hw); mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( LIMITS_POLLING_DELAY_MS)); mod_delayed_work(system_highpri_wq, &hw->freq_poll_work, msecs_to_jiffies(LIMITS_POLLING_DELAY_MS)); } } Loading @@ -218,7 +222,9 @@ static irqreturn_t lmh_dcvs_handle_isr(int irq, void *data) { struct limits_dcvs_hw *hw = data; mutex_lock(&hw->access_lock); lmh_dcvs_notify(hw); mutex_unlock(&hw->access_lock); return IRQ_HANDLED; } Loading Loading @@ -373,8 +379,8 @@ static int lmh_set_max_limit(int cpu, u32 freq) ret = limits_dcvs_write(hw->affinity, LIMITS_SUB_FN_THERMAL, LIMITS_FREQ_CAP, max_freq, (max_freq == U32_MAX) ? 0 : 1, 1); mutex_unlock(&hw->access_lock); lmh_dcvs_notify(hw); mutex_unlock(&hw->access_lock); return ret; } Loading Loading @@ -626,9 +632,7 @@ static int limits_dcvs_probe(struct platform_device *pdev) } mutex_init(&hw->access_lock); init_timer_deferrable(&hw->poll_timer); hw->poll_timer.data = (unsigned long)hw; hw->poll_timer.function = limits_dcvs_poll; INIT_DEFERRABLE_WORK(&hw->freq_poll_work, limits_dcvs_poll); hw->osm_hw_reg = devm_ioremap(&pdev->dev, request_reg, 0x4); if (!hw->osm_hw_reg) { pr_err("register remap failed\n"); Loading @@ -645,7 +649,7 @@ static int limits_dcvs_probe(struct platform_device *pdev) pr_err("Error getting IRQ number. err:%d\n", hw->irq_num); goto probe_exit; } atomic_set(&hw->is_irq_enabled, 1); hw->is_irq_enabled = true; ret = devm_request_threaded_irq(&pdev->dev, hw->irq_num, NULL, lmh_dcvs_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_SUSPEND, hw->sensor_name, hw); Loading Loading
drivers/thermal/qcom/msm_lmh_dcvs.c +21 −17 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -98,13 +98,13 @@ struct limits_dcvs_hw { void *int_clr_reg; void *min_freq_reg; cpumask_t core_map; struct timer_list poll_timer; struct delayed_work freq_poll_work; unsigned long max_freq; unsigned long min_freq; unsigned long hw_freq_limit; struct device_attribute lmh_freq_attr; struct list_head list; atomic_t is_irq_enabled; bool is_irq_enabled; struct mutex access_lock; struct __limits_cdev_data *cdev_data; struct regulator *isens_reg; Loading Loading @@ -184,33 +184,37 @@ static unsigned long limits_mitigation_notify(struct limits_dcvs_hw *hw) return max_limit; } static void limits_dcvs_poll(unsigned long data) static void limits_dcvs_poll(struct work_struct *work) { unsigned long max_limit = 0; struct limits_dcvs_hw *hw = (struct limits_dcvs_hw *)data; struct limits_dcvs_hw *hw = container_of(work, struct limits_dcvs_hw, freq_poll_work.work); mutex_lock(&hw->access_lock); if (hw->max_freq == UINT_MAX) limits_dcvs_get_freq_limits(cpumask_first(&hw->core_map), &hw->max_freq, &hw->min_freq); max_limit = limits_mitigation_notify(hw); if (max_limit >= hw->max_freq) { del_timer(&hw->poll_timer); writel_relaxed(0xFF, hw->int_clr_reg); atomic_set(&hw->is_irq_enabled, 1); hw->is_irq_enabled = true; enable_irq(hw->irq_num); } else { mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( LIMITS_POLLING_DELAY_MS)); mod_delayed_work(system_highpri_wq, &hw->freq_poll_work, msecs_to_jiffies(LIMITS_POLLING_DELAY_MS)); } mutex_unlock(&hw->access_lock); } static void lmh_dcvs_notify(struct limits_dcvs_hw *hw) { if (atomic_dec_and_test(&hw->is_irq_enabled)) { if (hw->is_irq_enabled) { hw->is_irq_enabled = false; disable_irq_nosync(hw->irq_num); limits_mitigation_notify(hw); mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( LIMITS_POLLING_DELAY_MS)); mod_delayed_work(system_highpri_wq, &hw->freq_poll_work, msecs_to_jiffies(LIMITS_POLLING_DELAY_MS)); } } Loading @@ -218,7 +222,9 @@ static irqreturn_t lmh_dcvs_handle_isr(int irq, void *data) { struct limits_dcvs_hw *hw = data; mutex_lock(&hw->access_lock); lmh_dcvs_notify(hw); mutex_unlock(&hw->access_lock); return IRQ_HANDLED; } Loading Loading @@ -373,8 +379,8 @@ static int lmh_set_max_limit(int cpu, u32 freq) ret = limits_dcvs_write(hw->affinity, LIMITS_SUB_FN_THERMAL, LIMITS_FREQ_CAP, max_freq, (max_freq == U32_MAX) ? 0 : 1, 1); mutex_unlock(&hw->access_lock); lmh_dcvs_notify(hw); mutex_unlock(&hw->access_lock); return ret; } Loading Loading @@ -626,9 +632,7 @@ static int limits_dcvs_probe(struct platform_device *pdev) } mutex_init(&hw->access_lock); init_timer_deferrable(&hw->poll_timer); hw->poll_timer.data = (unsigned long)hw; hw->poll_timer.function = limits_dcvs_poll; INIT_DEFERRABLE_WORK(&hw->freq_poll_work, limits_dcvs_poll); hw->osm_hw_reg = devm_ioremap(&pdev->dev, request_reg, 0x4); if (!hw->osm_hw_reg) { pr_err("register remap failed\n"); Loading @@ -645,7 +649,7 @@ static int limits_dcvs_probe(struct platform_device *pdev) pr_err("Error getting IRQ number. err:%d\n", hw->irq_num); goto probe_exit; } atomic_set(&hw->is_irq_enabled, 1); hw->is_irq_enabled = true; ret = devm_request_threaded_irq(&pdev->dev, hw->irq_num, NULL, lmh_dcvs_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_SUSPEND, hw->sensor_name, hw); Loading