diff options
Diffstat (limited to 'drivers/devfreq')
| -rw-r--r-- | drivers/devfreq/devfreq-event.c | 25 | ||||
| -rw-r--r-- | drivers/devfreq/devfreq.c | 110 | ||||
| -rw-r--r-- | drivers/devfreq/event/rockchip-dfi.c | 2 | ||||
| -rw-r--r-- | drivers/devfreq/governor_passive.c | 3 | ||||
| -rw-r--r-- | drivers/devfreq/governor_userspace.c | 3 | ||||
| -rw-r--r-- | drivers/devfreq/hisi_uncore_freq.c | 5 | ||||
| -rw-r--r-- | drivers/devfreq/imx8m-ddrc.c | 1 | ||||
| -rw-r--r-- | drivers/devfreq/tegra30-devfreq.c | 17 |
8 files changed, 94 insertions, 72 deletions
diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c index 70219099c604..9e183cd8818c 100644 --- a/drivers/devfreq/devfreq-event.c +++ b/drivers/devfreq/devfreq-event.c @@ -17,7 +17,13 @@ #include <linux/list.h> #include <linux/of.h> -static struct class *devfreq_event_class; +static struct attribute *devfreq_event_attrs[]; +ATTRIBUTE_GROUPS(devfreq_event); + +static const struct class devfreq_event_class = { + .name = "devfreq-event", + .dev_groups = devfreq_event_groups +}; /* The list of all devfreq event list */ static LIST_HEAD(devfreq_event_list); @@ -313,7 +319,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, if (!desc->ops->set_event || !desc->ops->get_event) return ERR_PTR(-EINVAL); - edev = kzalloc(sizeof(struct devfreq_event_dev), GFP_KERNEL); + edev = kzalloc_obj(struct devfreq_event_dev); if (!edev) return ERR_PTR(-ENOMEM); @@ -321,7 +327,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, edev->desc = desc; edev->enable_count = 0; edev->dev.parent = dev; - edev->dev.class = devfreq_event_class; + edev->dev.class = &devfreq_event_class; edev->dev.release = devfreq_event_release_edev; dev_set_name(&edev->dev, "event%d", atomic_inc_return(&event_no)); @@ -461,18 +467,15 @@ static struct attribute *devfreq_event_attrs[] = { &dev_attr_enable_count.attr, NULL, }; -ATTRIBUTE_GROUPS(devfreq_event); static int __init devfreq_event_init(void) { - devfreq_event_class = class_create("devfreq-event"); - if (IS_ERR(devfreq_event_class)) { - pr_err("%s: couldn't create class\n", __FILE__); - return PTR_ERR(devfreq_event_class); - } + int err; - devfreq_event_class->dev_groups = devfreq_event_groups; + err = class_register(&devfreq_event_class); + if (err) + pr_err("%s: couldn't create class\n", __FILE__); - return 0; + return err; } subsys_initcall(devfreq_event_init); diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 00979f2e0e27..82dd9a43dc62 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -38,6 +38,7 @@ static struct class *devfreq_class; static struct dentry *devfreq_debugfs; +static const struct attribute_group gov_attr_group; /* * devfreq core provides delayed work based load monitoring helper @@ -146,10 +147,9 @@ void devfreq_get_freq_range(struct devfreq *devfreq, DEV_PM_QOS_MIN_FREQUENCY); qos_max_freq = dev_pm_qos_read_value(devfreq->dev.parent, DEV_PM_QOS_MAX_FREQUENCY); - *min_freq = max(*min_freq, (unsigned long)HZ_PER_KHZ * qos_min_freq); + *min_freq = max(*min_freq, HZ_PER_KHZ * qos_min_freq); if (qos_max_freq != PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE) - *max_freq = min(*max_freq, - (unsigned long)HZ_PER_KHZ * qos_max_freq); + *max_freq = min(*max_freq, HZ_PER_KHZ * qos_max_freq); /* Apply constraints from OPP interface */ *max_freq = clamp(*max_freq, devfreq->scaling_min_freq, devfreq->scaling_max_freq); @@ -785,11 +785,6 @@ static void devfreq_dev_release(struct device *dev) kfree(devfreq); } -static void create_sysfs_files(struct devfreq *devfreq, - const struct devfreq_governor *gov); -static void remove_sysfs_files(struct devfreq *devfreq, - const struct devfreq_governor *gov); - /** * devfreq_add_device() - Add devfreq feature to the device * @dev: the device to add devfreq feature. @@ -821,7 +816,7 @@ struct devfreq *devfreq_add_device(struct device *dev, goto err_out; } - devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL); + devfreq = kzalloc_obj(struct devfreq); if (!devfreq) { err = -ENOMEM; goto err_out; @@ -956,7 +951,10 @@ struct devfreq *devfreq_add_device(struct device *dev, __func__); goto err_init; } - create_sysfs_files(devfreq, devfreq->governor); + + err = sysfs_update_group(&devfreq->dev.kobj, &gov_attr_group); + if (err) + goto err_init; list_add(&devfreq->node, &devfreq_list); @@ -995,12 +993,9 @@ int devfreq_remove_device(struct devfreq *devfreq) devfreq_cooling_unregister(devfreq->cdev); - if (devfreq->governor) { + if (devfreq->governor) devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_STOP, NULL); - remove_sysfs_files(devfreq, devfreq->governor); - } - device_unregister(&devfreq->dev); return 0; @@ -1460,7 +1455,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, __func__, df->governor->name, ret); goto out; } - remove_sysfs_files(df, df->governor); /* * Start the new governor and create the specific sysfs files @@ -1489,7 +1483,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, * Create the sysfs files for the new governor. But if failed to start * the new governor, restore the sysfs files of previous governor. */ - create_sysfs_files(df, df->governor); + ret = sysfs_update_group(&df->dev.kobj, &gov_attr_group); out: mutex_unlock(&devfreq_list_lock); @@ -1807,14 +1801,17 @@ static struct attribute *devfreq_attrs[] = { &dev_attr_trans_stat.attr, NULL, }; -ATTRIBUTE_GROUPS(devfreq); static ssize_t polling_interval_show(struct device *dev, struct device_attribute *attr, char *buf) { struct devfreq *df = to_devfreq(dev); - if (!df->profile) + /* Protect against race between sysfs attrs update and read/write */ + guard(mutex)(&devfreq_list_lock); + + if (!df->profile || !df->governor || + !IS_SUPPORTED_ATTR(df->governor->attrs, POLLING_INTERVAL)) return -EINVAL; return sprintf(buf, "%d\n", df->profile->polling_ms); @@ -1828,7 +1825,10 @@ static ssize_t polling_interval_store(struct device *dev, unsigned int value; int ret; - if (!df->governor) + guard(mutex)(&devfreq_list_lock); + + if (!df->governor || + !IS_SUPPORTED_ATTR(df->governor->attrs, POLLING_INTERVAL)) return -EINVAL; ret = sscanf(buf, "%u", &value); @@ -1847,7 +1847,10 @@ static ssize_t timer_show(struct device *dev, { struct devfreq *df = to_devfreq(dev); - if (!df->profile) + guard(mutex)(&devfreq_list_lock); + + if (!df->profile || !df->governor || + !IS_SUPPORTED_ATTR(df->governor->attrs, TIMER)) return -EINVAL; return sprintf(buf, "%s\n", timer_name[df->profile->timer]); @@ -1861,7 +1864,10 @@ static ssize_t timer_store(struct device *dev, struct device_attribute *attr, int timer = -1; int ret = 0, i; - if (!df->governor || !df->profile) + guard(mutex)(&devfreq_list_lock); + + if (!df->governor || !df->profile || + !IS_SUPPORTED_ATTR(df->governor->attrs, TIMER)) return -EINVAL; ret = sscanf(buf, "%16s", str_timer); @@ -1905,37 +1911,47 @@ out: } static DEVICE_ATTR_RW(timer); -#define CREATE_SYSFS_FILE(df, name) \ -{ \ - int ret; \ - ret = sysfs_create_file(&df->dev.kobj, &dev_attr_##name.attr); \ - if (ret < 0) { \ - dev_warn(&df->dev, \ - "Unable to create attr(%s)\n", "##name"); \ - } \ -} \ +static struct attribute *governor_attrs[] = { + &dev_attr_polling_interval.attr, + &dev_attr_timer.attr, + NULL +}; -/* Create the specific sysfs files which depend on each governor. */ -static void create_sysfs_files(struct devfreq *devfreq, - const struct devfreq_governor *gov) +static umode_t gov_attr_visible(struct kobject *kobj, + struct attribute *attr, int n) { - if (IS_SUPPORTED_ATTR(gov->attrs, POLLING_INTERVAL)) - CREATE_SYSFS_FILE(devfreq, polling_interval); - if (IS_SUPPORTED_ATTR(gov->attrs, TIMER)) - CREATE_SYSFS_FILE(devfreq, timer); -} + struct device *dev = kobj_to_dev(kobj); + struct devfreq *df = to_devfreq(dev); -/* Remove the specific sysfs files which depend on each governor. */ -static void remove_sysfs_files(struct devfreq *devfreq, - const struct devfreq_governor *gov) -{ - if (IS_SUPPORTED_ATTR(gov->attrs, POLLING_INTERVAL)) - sysfs_remove_file(&devfreq->dev.kobj, - &dev_attr_polling_interval.attr); - if (IS_SUPPORTED_ATTR(gov->attrs, TIMER)) - sysfs_remove_file(&devfreq->dev.kobj, &dev_attr_timer.attr); + if (!df->governor || !df->governor->attrs) + return 0; + + if (attr == &dev_attr_polling_interval.attr && + IS_SUPPORTED_ATTR(df->governor->attrs, POLLING_INTERVAL)) + return attr->mode; + + if (attr == &dev_attr_timer.attr && + IS_SUPPORTED_ATTR(df->governor->attrs, TIMER)) + return attr->mode; + + return 0; } +static const struct attribute_group devfreq_group = { + .attrs = devfreq_attrs, +}; + +static const struct attribute_group gov_attr_group = { + .attrs = governor_attrs, + .is_visible = gov_attr_visible, +}; + +static const struct attribute_group *devfreq_groups[] = { + &devfreq_group, + &gov_attr_group, + NULL +}; + /** * devfreq_summary_show() - Show the summary of the devfreq devices * @s: seq_file instance to show the summary of devfreq devices diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c index 5e6e7e900bda..255aee1bdd91 100644 --- a/drivers/devfreq/event/rockchip-dfi.c +++ b/drivers/devfreq/event/rockchip-dfi.c @@ -354,7 +354,7 @@ static ssize_t ddr_perf_cpumask_show(struct device *dev, struct pmu *pmu = dev_get_drvdata(dev); struct rockchip_dfi *dfi = container_of(pmu, struct rockchip_dfi, pmu); - return cpumap_print_to_pagebuf(true, buf, cpumask_of(dfi->cpu)); + return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(dfi->cpu))); } static struct device_attribute ddr_perf_cpumask_attr = diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c index 8cd6f9a59f64..d7feecd900f1 100644 --- a/drivers/devfreq/governor_passive.c +++ b/drivers/devfreq/governor_passive.c @@ -310,8 +310,7 @@ static int cpufreq_passive_register_notifier(struct devfreq *devfreq) continue; } - parent_cpu_data = kzalloc(sizeof(*parent_cpu_data), - GFP_KERNEL); + parent_cpu_data = kzalloc_obj(*parent_cpu_data); if (!parent_cpu_data) { ret = -ENOMEM; goto err_put_policy; diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c index 395174f93960..3906ebedbae8 100644 --- a/drivers/devfreq/governor_userspace.c +++ b/drivers/devfreq/governor_userspace.c @@ -87,8 +87,7 @@ static const struct attribute_group dev_attr_group = { static int userspace_init(struct devfreq *devfreq) { int err = 0; - struct userspace_data *data = kzalloc(sizeof(struct userspace_data), - GFP_KERNEL); + struct userspace_data *data = kzalloc_obj(struct userspace_data); if (!data) { err = -ENOMEM; diff --git a/drivers/devfreq/hisi_uncore_freq.c b/drivers/devfreq/hisi_uncore_freq.c index 4d00d813c8ac..ac55641b0259 100644 --- a/drivers/devfreq/hisi_uncore_freq.c +++ b/drivers/devfreq/hisi_uncore_freq.c @@ -18,7 +18,6 @@ #include <linux/ktime.h> #include <linux/mailbox_client.h> #include <linux/module.h> -#include <linux/mod_devicetable.h> #include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> @@ -475,7 +474,7 @@ static int hisi_uncore_mark_related_cpus(struct hisi_uncore_freq *uncore, return -EINVAL; len = rc; - u32 *num __free(kfree) = kcalloc(len, sizeof(*num), GFP_KERNEL); + u32 *num __free(kfree) = kzalloc_objs(*num, len); if (!num) return -ENOMEM; @@ -541,7 +540,7 @@ static ssize_t related_cpus_show(struct device *dev, { struct hisi_uncore_freq *uncore = dev_get_drvdata(dev->parent); - return cpumap_print_to_pagebuf(true, buf, &uncore->related_cpus); + return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&uncore->related_cpus)); } static DEVICE_ATTR_RO(related_cpus); diff --git a/drivers/devfreq/imx8m-ddrc.c b/drivers/devfreq/imx8m-ddrc.c index e1348490c8aa..52beeb5b7d65 100644 --- a/drivers/devfreq/imx8m-ddrc.c +++ b/drivers/devfreq/imx8m-ddrc.c @@ -3,7 +3,6 @@ * Copyright 2019 NXP */ -#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> diff --git a/drivers/devfreq/tegra30-devfreq.c b/drivers/devfreq/tegra30-devfreq.c index 8b57194ac698..401aac6a9f07 100644 --- a/drivers/devfreq/tegra30-devfreq.c +++ b/drivers/devfreq/tegra30-devfreq.c @@ -941,16 +941,22 @@ static int tegra_devfreq_probe(struct platform_device *pdev) return 0; } +/* + * The activity counter is incremented every 256 memory transactions. However, + * the number of clock cycles required for each transaction varies across + * different SoC generations. For instance, a single transaction takes 2 EMC + * clocks on Tegra30, 1 EMC clock on Tegra114, and 4 EMC clocks on Tegra124. + */ static const struct tegra_devfreq_soc_data tegra124_soc = { .configs = tegra124_device_configs, - - /* - * Activity counter is incremented every 256 memory transactions, - * and each transaction takes 4 EMC clocks. - */ .count_weight = 4 * 256, }; +static const struct tegra_devfreq_soc_data tegra114_soc = { + .configs = tegra124_device_configs, + .count_weight = 256, +}; + static const struct tegra_devfreq_soc_data tegra30_soc = { .configs = tegra30_device_configs, .count_weight = 2 * 256, @@ -958,6 +964,7 @@ static const struct tegra_devfreq_soc_data tegra30_soc = { static const struct of_device_id tegra_devfreq_of_match[] = { { .compatible = "nvidia,tegra30-actmon", .data = &tegra30_soc, }, + { .compatible = "nvidia,tegra114-actmon", .data = &tegra114_soc, }, { .compatible = "nvidia,tegra124-actmon", .data = &tegra124_soc, }, { }, }; |
