diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 0a94125d8c50..839de3cb3c98 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -85,6 +85,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 @@ -518,6 +558,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, @@ -1096,7 +1142,7 @@ static ssize_t trans_stat_show(struct device *dev, 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, "%8lu", devfreq->profile->freq_table[i]); len += sprintf(buf + len, " time(ms)\n"); @@ -1108,7 +1154,7 @@ static ssize_t trans_stat_show(struct device *dev, } else { len += sprintf(buf + len, " "); } - len += sprintf(buf + len, "%8u:", + len += sprintf(buf + len, "%8lu:", devfreq->profile->freq_table[i]); for (j = 0; j < max_state; j++) len += sprintf(buf + len, "%8u", diff --git a/drivers/staging/imgtec/rogue/pvr_dvfs_device.c b/drivers/staging/imgtec/rogue/pvr_dvfs_device.c index 94804a43dba3..24af5c7baa08 100644 --- a/drivers/staging/imgtec/rogue/pvr_dvfs_device.c +++ b/drivers/staging/imgtec/rogue/pvr_dvfs_device.c @@ -240,17 +240,8 @@ static int GetOPPValues(struct device *dev, struct OPP_STRUCT *opp; int count, i, err = 0; unsigned long freq; - - /* ChromiumOS kernels are carrying a fix which changes the type of - * freq_table in struct devfreq_dev_profile to 'unsigned long'. - * However, this change has not been merged upstream, so we need - * to support using the older 'unsigned int' type too. - */ -#if defined(CHROMIUMOS_WORKAROUNDS_KERNEL318) unsigned long *freq_table; -#else - unsigned int *freq_table; -#endif + /* Start RCU read-side critical section to access device opp_list. */ rcu_read_lock(); diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index 073cec2659f2..98c699304e12 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -96,7 +96,7 @@ struct devfreq_dev_profile { int (*get_cur_freq)(struct device *dev, unsigned long *freq); void (*exit)(struct device *dev); - unsigned int *freq_table; + unsigned long *freq_table; unsigned int max_state; };