cpufreq: governor: Always schedule work on the CPU running update
[deliverable/linux.git] / drivers / devfreq / devfreq.c
index 49fc7dcf664cc271ff19f2388d10ca90008f71b7..984c5e9e7bdd5bd72f66d0706661435f17b20b85 100644 (file)
@@ -84,6 +84,46 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
        return -EINVAL;
 }
 
+/**
+ * devfreq_set_freq_table() - Initialize freq_table for the frequency
+ * @devfreq:   the devfreq instance
+ */
+static void devfreq_set_freq_table(struct devfreq *devfreq)
+{
+       struct devfreq_dev_profile *profile = devfreq->profile;
+       struct dev_pm_opp *opp;
+       unsigned long freq;
+       int i, count;
+
+       /* Initialize the freq_table from OPP table */
+       count = dev_pm_opp_get_opp_count(devfreq->dev.parent);
+       if (count <= 0)
+               return;
+
+       profile->max_state = count;
+       profile->freq_table = devm_kcalloc(devfreq->dev.parent,
+                                       profile->max_state,
+                                       sizeof(*profile->freq_table),
+                                       GFP_KERNEL);
+       if (!profile->freq_table) {
+               profile->max_state = 0;
+               return;
+       }
+
+       rcu_read_lock();
+       for (i = 0, freq = 0; i < profile->max_state; i++, freq++) {
+               opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
+               if (IS_ERR(opp)) {
+                       devm_kfree(devfreq->dev.parent, profile->freq_table);
+                       profile->max_state = 0;
+                       rcu_read_unlock();
+                       return;
+               }
+               profile->freq_table[i] = freq;
+       }
+       rcu_read_unlock();
+}
+
 /**
  * devfreq_update_status() - Update statistics of devfreq behavior
  * @devfreq:   the devfreq instance
@@ -478,6 +518,12 @@ struct devfreq *devfreq_add_device(struct device *dev,
        devfreq->data = data;
        devfreq->nb.notifier_call = devfreq_notifier_call;
 
+       if (!devfreq->profile->max_state && !devfreq->profile->freq_table) {
+               mutex_unlock(&devfreq->lock);
+               devfreq_set_freq_table(devfreq);
+               mutex_lock(&devfreq->lock);
+       }
+
        devfreq->trans_table =  devm_kzalloc(dev, sizeof(unsigned int) *
                                                devfreq->profile->max_state *
                                                devfreq->profile->max_state,
@@ -1003,11 +1049,13 @@ static ssize_t trans_stat_show(struct device *dev,
        if (!devfreq->stop_polling &&
                        devfreq_update_status(devfreq, devfreq->previous_freq))
                return 0;
+       if (max_state == 0)
+               return sprintf(buf, "Not Supported.\n");
 
-       len = sprintf(buf, "   From  :   To\n");
-       len += sprintf(buf + len, "         :");
+       len = sprintf(buf, "     From  :   To\n");
+       len += sprintf(buf + len, "           :");
        for (i = 0; i < max_state; i++)
-               len += sprintf(buf + len, "%8u",
+               len += sprintf(buf + len, "%10lu",
                                devfreq->profile->freq_table[i]);
 
        len += sprintf(buf + len, "   time(ms)\n");
@@ -1019,10 +1067,10 @@ static ssize_t trans_stat_show(struct device *dev,
                } else {
                        len += sprintf(buf + len, " ");
                }
-               len += sprintf(buf + len, "%8u:",
+               len += sprintf(buf + len, "%10lu:",
                                devfreq->profile->freq_table[i]);
                for (j = 0; j < max_state; j++)
-                       len += sprintf(buf + len, "%8u",
+                       len += sprintf(buf + len, "%10u",
                                devfreq->trans_table[(i * max_state) + j]);
                len += sprintf(buf + len, "%10u\n",
                        jiffies_to_msecs(devfreq->time_in_state[i]));
This page took 0.026825 seconds and 5 git commands to generate.