root/drivers/devfreq/governor_simpleondemand.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. devfreq_simple_ondemand_func
  2. devfreq_simple_ondemand_handler
  3. devfreq_simple_ondemand_init
  4. devfreq_simple_ondemand_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  linux/drivers/devfreq/governor_simpleondemand.c
   4  *
   5  *  Copyright (C) 2011 Samsung Electronics
   6  *      MyungJoo Ham <myungjoo.ham@samsung.com>
   7  */
   8 
   9 #include <linux/errno.h>
  10 #include <linux/module.h>
  11 #include <linux/devfreq.h>
  12 #include <linux/math64.h>
  13 #include "governor.h"
  14 
  15 /* Default constants for DevFreq-Simple-Ondemand (DFSO) */
  16 #define DFSO_UPTHRESHOLD        (90)
  17 #define DFSO_DOWNDIFFERENCTIAL  (5)
  18 static int devfreq_simple_ondemand_func(struct devfreq *df,
  19                                         unsigned long *freq)
  20 {
  21         int err;
  22         struct devfreq_dev_status *stat;
  23         unsigned long long a, b;
  24         unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
  25         unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
  26         struct devfreq_simple_ondemand_data *data = df->data;
  27 
  28         err = devfreq_update_stats(df);
  29         if (err)
  30                 return err;
  31 
  32         stat = &df->last_status;
  33 
  34         if (data) {
  35                 if (data->upthreshold)
  36                         dfso_upthreshold = data->upthreshold;
  37                 if (data->downdifferential)
  38                         dfso_downdifferential = data->downdifferential;
  39         }
  40         if (dfso_upthreshold > 100 ||
  41             dfso_upthreshold < dfso_downdifferential)
  42                 return -EINVAL;
  43 
  44         /* Assume MAX if it is going to be divided by zero */
  45         if (stat->total_time == 0) {
  46                 *freq = DEVFREQ_MAX_FREQ;
  47                 return 0;
  48         }
  49 
  50         /* Prevent overflow */
  51         if (stat->busy_time >= (1 << 24) || stat->total_time >= (1 << 24)) {
  52                 stat->busy_time >>= 7;
  53                 stat->total_time >>= 7;
  54         }
  55 
  56         /* Set MAX if it's busy enough */
  57         if (stat->busy_time * 100 >
  58             stat->total_time * dfso_upthreshold) {
  59                 *freq = DEVFREQ_MAX_FREQ;
  60                 return 0;
  61         }
  62 
  63         /* Set MAX if we do not know the initial frequency */
  64         if (stat->current_frequency == 0) {
  65                 *freq = DEVFREQ_MAX_FREQ;
  66                 return 0;
  67         }
  68 
  69         /* Keep the current frequency */
  70         if (stat->busy_time * 100 >
  71             stat->total_time * (dfso_upthreshold - dfso_downdifferential)) {
  72                 *freq = stat->current_frequency;
  73                 return 0;
  74         }
  75 
  76         /* Set the desired frequency based on the load */
  77         a = stat->busy_time;
  78         a *= stat->current_frequency;
  79         b = div_u64(a, stat->total_time);
  80         b *= 100;
  81         b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
  82         *freq = (unsigned long) b;
  83 
  84         return 0;
  85 }
  86 
  87 static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
  88                                 unsigned int event, void *data)
  89 {
  90         switch (event) {
  91         case DEVFREQ_GOV_START:
  92                 devfreq_monitor_start(devfreq);
  93                 break;
  94 
  95         case DEVFREQ_GOV_STOP:
  96                 devfreq_monitor_stop(devfreq);
  97                 break;
  98 
  99         case DEVFREQ_GOV_INTERVAL:
 100                 devfreq_interval_update(devfreq, (unsigned int *)data);
 101                 break;
 102 
 103         case DEVFREQ_GOV_SUSPEND:
 104                 devfreq_monitor_suspend(devfreq);
 105                 break;
 106 
 107         case DEVFREQ_GOV_RESUME:
 108                 devfreq_monitor_resume(devfreq);
 109                 break;
 110 
 111         default:
 112                 break;
 113         }
 114 
 115         return 0;
 116 }
 117 
 118 static struct devfreq_governor devfreq_simple_ondemand = {
 119         .name = DEVFREQ_GOV_SIMPLE_ONDEMAND,
 120         .get_target_freq = devfreq_simple_ondemand_func,
 121         .event_handler = devfreq_simple_ondemand_handler,
 122 };
 123 
 124 static int __init devfreq_simple_ondemand_init(void)
 125 {
 126         return devfreq_add_governor(&devfreq_simple_ondemand);
 127 }
 128 subsys_initcall(devfreq_simple_ondemand_init);
 129 
 130 static void __exit devfreq_simple_ondemand_exit(void)
 131 {
 132         int ret;
 133 
 134         ret = devfreq_remove_governor(&devfreq_simple_ondemand);
 135         if (ret)
 136                 pr_err("%s: failed remove governor %d\n", __func__, ret);
 137 
 138         return;
 139 }
 140 module_exit(devfreq_simple_ondemand_exit);
 141 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */