]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
ARM: tegra: power: Track grading interval with timer
authorAlex Frid <afrid@nvidia.com>
Thu, 10 Apr 2014 22:23:51 +0000 (15:23 -0700)
committerMandar Padmawar <mpadmawar@nvidia.com>
Tue, 20 May 2014 09:27:46 +0000 (02:27 -0700)
Added kernel timer to track grading interval. Check timer expiration
flag in grading callback instead of reading and checking time directly.
It reduced some CPU cycles within each callback invocation.

Bug 1343366

Change-Id: I6ba901e34b737cae760ead944ee344722d2eb47c
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/400717
(cherry picked from commit 228c7221be7d39724f739b3dc563ce4c9722dc99)
Reviewed-on: http://git-master/r/407058
(cherry picked from commit f5ce03476dcc33950082a9a88be27d793a629a04)
Reviewed-on: http://git-master/r/410539
GVS: Gerrit_Virtual_Submit
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
arch/arm/mach-tegra/tegra_simon.c
arch/arm/mach-tegra/tegra_simon.h

index 3861e203a4e615f0062cadcf38c69a608d99af32..3187418cc138c3bfcfebfe117cb567d17222f4b9 100644 (file)
@@ -85,23 +85,49 @@ static void tegra_simon_reset_grade(unsigned long data)
        schedule_work(&grader->grade_update_work);
 }
 
-static void tegra_simon_grade_set(struct tegra_simon_grader *grader,
-                                 int grade, bool restart)
+static inline void mod_grading_timer_on_grade(struct tegra_simon_grader *grader)
+{
+       if (grader->grade) {
+               /* restart timer while at high grade */
+               struct timespec ts = {grading_sec, 0};
+               mod_timer(&grader->grade_timer,
+                         jiffies + timespec_to_jiffies(&ts));
+       }
+}
+
+static void tegra_simon_restart_grader(unsigned long data)
+{
+       unsigned long flags;
+       struct tegra_simon_grader *grader = (struct tegra_simon_grader *)data;
+
+       spin_lock_irqsave(&grader->grade_lock, flags);
+       if (grader->grade) {
+               /* restart grading while at high grade */
+               grader->stop_grading = false;
+               pr_info("%s: %s grader restarted\n",
+                       __func__, grader->domain_name);
+       }
+       spin_unlock_irqrestore(&grader->grade_lock, flags);
+}
+
+static void tegra_simon_grade_set(struct tegra_simon_grader *grader, int grade)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&grader->grade_lock, flags);
 
-       /* once low grade is detected, stop grading (unless restart request) */
-       grader->stop_grading = !grade && !restart;
+       /* once grading is successful, stop grading, and restart timers */
+       grader->stop_grading = true;
 
        if (grader->grade == grade) {
                mod_wdt_on_grade(grader);
+               mod_grading_timer_on_grade(grader);
                spin_unlock_irqrestore(&grader->grade_lock, flags);
                return;
        }
        grader->grade = grade;
        mod_wdt_on_grade(grader);
+       mod_grading_timer_on_grade(grader);
        spin_unlock_irqrestore(&grader->grade_lock, flags);
 
        schedule_work(&grader->grade_update_work);
@@ -119,7 +145,6 @@ static int tegra_simon_gpu_grading_cb(
        int mv = (int)((long)v);
        struct tegra_simon_grader *grader = container_of(
                nb, struct tegra_simon_grader, grading_condition_nb);
-       ktime_t now = ktime_get();
        unsigned long t;
        int grade = 0;
 
@@ -133,11 +158,6 @@ static int tegra_simon_gpu_grading_cb(
        if ((mv <= 0) || (mv > grader->desc->grading_mv_max))
                return NOTIFY_OK;
 
-       if (grader->last_grading.tv64 &&
-           (ktime_to_ms(ktime_sub(now, grader->last_grading)) <
-            (s64)grading_sec * 1000))
-               return NOTIFY_OK;
-
        if (grader->tzd->ops->get_temp(grader->tzd, &t)) {
                pr_err("%s: Failed to get %s temperature\n",
                       __func__, grader->domain_name);
@@ -157,8 +177,8 @@ static int tegra_simon_gpu_grading_cb(
                }
        }
 
-       grader->last_grading = now;
-       tegra_simon_grade_set(grader, grade, false);
+       grader->last_grading = ktime_get();
+       tegra_simon_grade_set(grader, grade);
        pr_info("%s: graded %s: v = %d, t = %lu, grade = %d\n",
                __func__, grader->domain_name, mv, t, grade);
        return NOTIFY_OK;
@@ -171,6 +191,8 @@ static int __init tegra_simon_init_gpu(void)
                &simon_graders[TEGRA_SIMON_DOMAIN_GPU];
 
        spin_lock_init(&grader->grade_lock);
+       setup_timer(&grader->grade_timer, tegra_simon_restart_grader,
+                   (unsigned long)grader);
        setup_timer(&grader->grade_wdt, tegra_simon_reset_grade,
                    (unsigned long)grader);
        INIT_WORK(&grader->grade_update_work, tegra_simon_grade_notify);
@@ -213,7 +235,6 @@ static int tegra_simon_cpu_grading_cb(
        struct tegra_simon_grader *grader = container_of(
                nb, struct tegra_simon_grader, grading_condition_nb);
        struct tegra_cl_dvfs *cld;
-       ktime_t now = ktime_get();
 
        unsigned long t;
        int mv;
@@ -226,11 +247,6 @@ static int tegra_simon_cpu_grading_cb(
            !tegra_dvfs_rail_is_dfll_mode(tegra_cpu_rail))
                return NOTIFY_OK;
 
-       if (grader->last_grading.tv64 &&
-           (ktime_to_ms(ktime_sub(now, grader->last_grading)) <
-            (s64)grading_sec * 1000))
-               return NOTIFY_OK;
-
        if (grader->tzd->ops->get_temp(grader->tzd, &t)) {
                pr_err("%s: Failed to get %s temperature\n",
                       __func__, grader->domain_name);
@@ -268,8 +284,8 @@ static int tegra_simon_cpu_grading_cb(
        }
        tegra_cl_dvfs_clamp_at_vmin(cld, false);
 
-       grader->last_grading = now;
-       tegra_simon_grade_set(grader, grade, false);
+       grader->last_grading = ktime_get();
+       tegra_simon_grade_set(grader, grade);
        pr_info("%s: graded %s: v = %d, t = %lu, grade = %d\n",
                __func__, grader->domain_name, mv, t, grade);
        return NOTIFY_OK;
@@ -283,6 +299,8 @@ static int __init tegra_simon_init_cpu(void)
        int r;
 
        spin_lock_init(&grader->grade_lock);
+       setup_timer(&grader->grade_timer, tegra_simon_restart_grader,
+                   (unsigned long)grader);
        setup_timer(&grader->grade_wdt, tegra_simon_reset_grade,
                    (unsigned long)grader);
        INIT_WORK(&grader->grade_update_work, tegra_simon_grade_notify);
@@ -417,11 +435,10 @@ static int grade_set(void *data, u64 val)
                return -EINVAL;
 
        if (!grader->desc && (grader->grade != grade)) {
-               grader->stop_grading = false;
                grader->grade = grade;
                grade_notify(grader);
        } else if (grader->desc) {
-               tegra_simon_grade_set(grader, grade, true);
+               tegra_simon_grade_set(grader, grade);
        }
        return 0;
 }
index acc58919c0fd1ae1c51ee380f11e3e264f26e94c..b6702219471701ecd56c5bfb5aea3d4e173fa9dc 100644 (file)
@@ -44,6 +44,7 @@ struct tegra_simon_grader {
 
        spinlock_t                      grade_lock;
        struct timer_list               grade_wdt;
+       struct timer_list               grade_timer;
        ktime_t                         last_grading;
        bool                            stop_grading;
        int                             grade;