From 95adb4e59263d3056d75eb385e79f9e037b5b7bc Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 31 May 2017 17:59:26 +0100 Subject: arm: fix return value of parse_cpu_capacity parse_cpu_capacity() has to return 0 on failure, but it currently returns 1 instead if raw_capacity kcalloc failed. Fix it (by directly returning 0). Reported-by: Morten Rasmussen Fixes: 06073ee26775 ('ARM: 8621/3: parse cpu capacity-dmips-mhz from DT') Signed-off-by: Juri Lelli Acked-by: Russell King Acked-by: Vincent Guittot Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index f8a3ab82e77f..1b8ec3054642 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -166,7 +166,7 @@ static int __init parse_cpu_capacity(struct device_node *cpu_node, int cpu) if (!raw_capacity) { pr_err("cpu_capacity: failed to allocate memory for raw capacities\n"); cap_parsing_failed = true; - return !ret; + return 0; } } capacity_scale = max(cpu_capacity, capacity_scale); -- cgit From f70b281b59a871545362a494d99a644153fbbaac Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 31 May 2017 17:59:27 +0100 Subject: arm: remove wrong CONFIG_PROC_SYSCTL ifdef The sysfs cpu_capacity entry for each CPU has nothing to do with PROC_FS, nor it's in /proc/sys path. Remove such ifdef. Cc: Russell King Reported-and-suggested-by: Sudeep Holla Fixes: 7e5930aaef5d ('ARM: 8622/3: add sysfs cpu_capacity attribute') Signed-off-by: Juri Lelli Acked-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/topology.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 1b8ec3054642..40dd35aa46d0 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -57,7 +57,6 @@ static void set_capacity_scale(unsigned int cpu, unsigned long capacity) per_cpu(cpu_scale, cpu) = capacity; } -#ifdef CONFIG_PROC_SYSCTL static ssize_t cpu_capacity_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -114,7 +113,6 @@ static int register_cpu_capacity_sysctl(void) return 0; } subsys_initcall(register_cpu_capacity_sysctl); -#endif #ifdef CONFIG_OF struct cpu_efficiency { -- cgit From 2ef7a2953c81ee6b341e3ffb33570adc894cf4a5 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 31 May 2017 17:59:28 +0100 Subject: arm, arm64: factorize common cpu capacity default code arm and arm64 share lot of code relative to parsing CPU capacity information from DT, using that information for appropriate scaling and exposing a sysfs interface for chaging such values at runtime. Factorize such code in a common place (driver/base/arch_topology.c) in preparation for further additions. Suggested-by: Will Deacon Suggested-by: Mark Rutland Suggested-by: Catalin Marinas Cc: Russell King Cc: Catalin Marinas Cc: Will Deacon Cc: Greg Kroah-Hartman Signed-off-by: Juri Lelli Acked-by: Russell King Acked-by: Catalin Marinas Acked-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- arch/arm/Kconfig | 1 + arch/arm/kernel/topology.c | 213 ++------------------------------------------- 2 files changed, 7 insertions(+), 207 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4c1a35f15838..7ef16700cb88 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -25,6 +25,7 @@ config ARM select EDAC_SUPPORT select EDAC_ATOMIC_SCRUB select GENERIC_ALLOCATOR + select GENERIC_ARCH_TOPOLOGY if ARM_CPU_TOPOLOGY select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI) select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_CPU_AUTOPROBE diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 40dd35aa46d0..49ef025ffaa0 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -44,75 +44,10 @@ * to run the rebalance_domains for all idle cores and the cpu_capacity can be * updated during this sequence. */ -static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE; -static DEFINE_MUTEX(cpu_scale_mutex); -unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu) -{ - return per_cpu(cpu_scale, cpu); -} - -static void set_capacity_scale(unsigned int cpu, unsigned long capacity) -{ - per_cpu(cpu_scale, cpu) = capacity; -} - -static ssize_t cpu_capacity_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct cpu *cpu = container_of(dev, struct cpu, dev); - - return sprintf(buf, "%lu\n", - arch_scale_cpu_capacity(NULL, cpu->dev.id)); -} - -static ssize_t cpu_capacity_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct cpu *cpu = container_of(dev, struct cpu, dev); - int this_cpu = cpu->dev.id, i; - unsigned long new_capacity; - ssize_t ret; - - if (count) { - ret = kstrtoul(buf, 0, &new_capacity); - if (ret) - return ret; - if (new_capacity > SCHED_CAPACITY_SCALE) - return -EINVAL; - - mutex_lock(&cpu_scale_mutex); - for_each_cpu(i, &cpu_topology[this_cpu].core_sibling) - set_capacity_scale(i, new_capacity); - mutex_unlock(&cpu_scale_mutex); - } - - return count; -} - -static DEVICE_ATTR_RW(cpu_capacity); - -static int register_cpu_capacity_sysctl(void) -{ - int i; - struct device *cpu; - - for_each_possible_cpu(i) { - cpu = get_cpu_device(i); - if (!cpu) { - pr_err("%s: too early to get CPU%d device!\n", - __func__, i); - continue; - } - device_create_file(cpu, &dev_attr_cpu_capacity); - } - - return 0; -} -subsys_initcall(register_cpu_capacity_sysctl); +extern unsigned long +arch_scale_cpu_capacity(struct sched_domain *sd, int cpu); +extern void set_capacity_scale(unsigned int cpu, unsigned long capacity); #ifdef CONFIG_OF struct cpu_efficiency { @@ -141,145 +76,9 @@ static unsigned long *__cpu_capacity; static unsigned long middle_capacity = 1; static bool cap_from_dt = true; -static u32 *raw_capacity; -static bool cap_parsing_failed; -static u32 capacity_scale; - -static int __init parse_cpu_capacity(struct device_node *cpu_node, int cpu) -{ - int ret = 1; - u32 cpu_capacity; - - if (cap_parsing_failed) - return !ret; - - ret = of_property_read_u32(cpu_node, - "capacity-dmips-mhz", - &cpu_capacity); - if (!ret) { - if (!raw_capacity) { - raw_capacity = kcalloc(num_possible_cpus(), - sizeof(*raw_capacity), - GFP_KERNEL); - if (!raw_capacity) { - pr_err("cpu_capacity: failed to allocate memory for raw capacities\n"); - cap_parsing_failed = true; - return 0; - } - } - capacity_scale = max(cpu_capacity, capacity_scale); - raw_capacity[cpu] = cpu_capacity; - pr_debug("cpu_capacity: %s cpu_capacity=%u (raw)\n", - cpu_node->full_name, raw_capacity[cpu]); - } else { - if (raw_capacity) { - pr_err("cpu_capacity: missing %s raw capacity\n", - cpu_node->full_name); - pr_err("cpu_capacity: partial information: fallback to 1024 for all CPUs\n"); - } - cap_parsing_failed = true; - kfree(raw_capacity); - } - - return !ret; -} - -static void normalize_cpu_capacity(void) -{ - u64 capacity; - int cpu; - - if (!raw_capacity || cap_parsing_failed) - return; - - pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale); - mutex_lock(&cpu_scale_mutex); - for_each_possible_cpu(cpu) { - capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT) - / capacity_scale; - set_capacity_scale(cpu, capacity); - pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n", - cpu, arch_scale_cpu_capacity(NULL, cpu)); - } - mutex_unlock(&cpu_scale_mutex); -} - -#ifdef CONFIG_CPU_FREQ -static cpumask_var_t cpus_to_visit; -static bool cap_parsing_done; -static void parsing_done_workfn(struct work_struct *work); -static DECLARE_WORK(parsing_done_work, parsing_done_workfn); - -static int -init_cpu_capacity_callback(struct notifier_block *nb, - unsigned long val, - void *data) -{ - struct cpufreq_policy *policy = data; - int cpu; - - if (cap_parsing_failed || cap_parsing_done) - return 0; - - switch (val) { - case CPUFREQ_NOTIFY: - pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n", - cpumask_pr_args(policy->related_cpus), - cpumask_pr_args(cpus_to_visit)); - cpumask_andnot(cpus_to_visit, - cpus_to_visit, - policy->related_cpus); - for_each_cpu(cpu, policy->related_cpus) { - raw_capacity[cpu] = arch_scale_cpu_capacity(NULL, cpu) * - policy->cpuinfo.max_freq / 1000UL; - capacity_scale = max(raw_capacity[cpu], capacity_scale); - } - if (cpumask_empty(cpus_to_visit)) { - normalize_cpu_capacity(); - kfree(raw_capacity); - pr_debug("cpu_capacity: parsing done\n"); - cap_parsing_done = true; - schedule_work(&parsing_done_work); - } - } - return 0; -} - -static struct notifier_block init_cpu_capacity_notifier = { - .notifier_call = init_cpu_capacity_callback, -}; - -static int __init register_cpufreq_notifier(void) -{ - if (cap_parsing_failed) - return -EINVAL; - - if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL)) { - pr_err("cpu_capacity: failed to allocate memory for cpus_to_visit\n"); - return -ENOMEM; - } - cpumask_copy(cpus_to_visit, cpu_possible_mask); - - return cpufreq_register_notifier(&init_cpu_capacity_notifier, - CPUFREQ_POLICY_NOTIFIER); -} -core_initcall(register_cpufreq_notifier); - -static void parsing_done_workfn(struct work_struct *work) -{ - cpufreq_unregister_notifier(&init_cpu_capacity_notifier, - CPUFREQ_POLICY_NOTIFIER); -} - -#else -static int __init free_raw_capacity(void) -{ - kfree(raw_capacity); - - return 0; -} -core_initcall(free_raw_capacity); -#endif +extern bool cap_parsing_failed; +extern void normalize_cpu_capacity(void); +extern int __init parse_cpu_capacity(struct device_node *cpu_node, int cpu); /* * Iterate all CPUs' descriptor in DT and compute the efficiency -- cgit From c105aa31183a6ebec395681b6df47c8b65259322 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 31 May 2017 17:59:29 +0100 Subject: arm,arm64,drivers: reduce scope of cap_parsing_failed Reduce the scope of cap_parsing_failed (making it static in drivers/base/arch_topology.c) by slightly changing {arm,arm64} DT parsing code. For arm checking for !cap_parsing_failed before calling normalize_ cpu_capacity() is superfluous, as returning an error from parse_ cpu_capacity() (above) means cap_from _dt is set to false. For arm64 we can simply check if raw_capacity points to something, which is not if capacity parsing has failed. Suggested-by: Morten Rasmussen Signed-off-by: Juri Lelli Acked-by: Russell King Acked-by: Catalin Marinas Acked-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/topology.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 49ef025ffaa0..1e35a3265ddf 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -76,7 +76,6 @@ static unsigned long *__cpu_capacity; static unsigned long middle_capacity = 1; static bool cap_from_dt = true; -extern bool cap_parsing_failed; extern void normalize_cpu_capacity(void); extern int __init parse_cpu_capacity(struct device_node *cpu_node, int cpu); @@ -165,7 +164,7 @@ static void __init parse_dt_topology(void) middle_capacity = ((max_capacity / 3) >> (SCHED_CAPACITY_SHIFT-1)) + 1; - if (cap_from_dt && !cap_parsing_failed) + if (cap_from_dt) normalize_cpu_capacity(); } -- cgit From 615ffd63149117aa5693d6672944966b490cdb66 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 31 May 2017 17:59:30 +0100 Subject: arm,arm64,drivers: move externs in a new header file Create a new header file (include/linux/arch_topology.h) and put there declarations of interfaces used by arm, arm64 and drivers code. Signed-off-by: Juri Lelli Acked-by: Russell King Acked-by: Catalin Marinas Acked-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/topology.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 1e35a3265ddf..557be4f1d2d7 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -11,6 +11,7 @@ * for more details. */ +#include #include #include #include @@ -45,10 +46,6 @@ * updated during this sequence. */ -extern unsigned long -arch_scale_cpu_capacity(struct sched_domain *sd, int cpu); -extern void set_capacity_scale(unsigned int cpu, unsigned long capacity); - #ifdef CONFIG_OF struct cpu_efficiency { const char *compatible; @@ -76,8 +73,6 @@ static unsigned long *__cpu_capacity; static unsigned long middle_capacity = 1; static bool cap_from_dt = true; -extern void normalize_cpu_capacity(void); -extern int __init parse_cpu_capacity(struct device_node *cpu_node, int cpu); /* * Iterate all CPUs' descriptor in DT and compute the efficiency -- cgit From 4ca4f26a9c66103ca158689b7554f07f4968a32c Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 31 May 2017 17:59:31 +0100 Subject: arm,arm64,drivers: add a prefix to drivers arch_topology interfaces Now that some functions that deal with arch topology information live under drivers, there is a clash of naming that might create confusion. Tidy things up by creating a topology namespace for interfaces used by arch code; achieve this by prepending a 'topology_' prefix to driver interfaces. Signed-off-by: Juri Lelli Acked-by: Russell King Acked-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/topology.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 557be4f1d2d7..bf949a763dbe 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -111,7 +111,7 @@ static void __init parse_dt_topology(void) continue; } - if (parse_cpu_capacity(cn, cpu)) { + if (topology_parse_cpu_capacity(cn, cpu)) { of_node_put(cn); continue; } @@ -160,7 +160,7 @@ static void __init parse_dt_topology(void) >> (SCHED_CAPACITY_SHIFT-1)) + 1; if (cap_from_dt) - normalize_cpu_capacity(); + topology_normalize_cpu_scale(); } /* @@ -173,10 +173,10 @@ static void update_cpu_capacity(unsigned int cpu) if (!cpu_capacity(cpu) || cap_from_dt) return; - set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity); + topology_set_cpu_scale(cpu, cpu_capacity(cpu) / middle_capacity); pr_info("CPU%u: update cpu_capacity %lu\n", - cpu, arch_scale_cpu_capacity(NULL, cpu)); + cpu, topology_get_cpu_scale(NULL, cpu)); } #else -- cgit From 71d1e5d71cec76e927a92354a7eb9d476e7054ad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 Jun 2017 14:14:16 +0200 Subject: arm: ecard: use dev_groups and not dev_attrs for bus_type The dev_attrs field has long been "depreciated" and is finally being removed, so move the driver to use the "correct" dev_groups field instead for struct bus_type. Cc: Russell King Cc: Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-rpc/ecard.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c index 6b279d037774..f75b8b562d57 100644 --- a/arch/arm/mach-rpc/ecard.c +++ b/arch/arm/mach-rpc/ecard.c @@ -761,19 +761,21 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot) return ec; } -static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t irq_show(struct device *dev, struct device_attribute *attr, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); return sprintf(buf, "%u\n", ec->irq); } +static DEVICE_ATTR_RO(irq); -static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t dma_show(struct device *dev, struct device_attribute *attr, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); return sprintf(buf, "%u\n", ec->dma); } +static DEVICE_ATTR_RO(dma); -static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t resource_show(struct device *dev, struct device_attribute *attr, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); char *str = buf; @@ -787,35 +789,39 @@ static ssize_t ecard_show_resources(struct device *dev, struct device_attribute return str - buf; } +static DEVICE_ATTR_RO(resource_show) -static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t vendor_show(struct device *dev, struct device_attribute *attr, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); return sprintf(buf, "%u\n", ec->cid.manufacturer); } +static DEVICE_ATTR_RO(vendor); -static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t device_show(struct device *dev, struct device_attribute *attr, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); return sprintf(buf, "%u\n", ec->cid.product); } +static DEVICE_ATTR_RO(device); -static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); return sprintf(buf, "%s\n", ec->easi ? "EASI" : "IOC"); } - -static struct device_attribute ecard_dev_attrs[] = { - __ATTR(device, S_IRUGO, ecard_show_device, NULL), - __ATTR(dma, S_IRUGO, ecard_show_dma, NULL), - __ATTR(irq, S_IRUGO, ecard_show_irq, NULL), - __ATTR(resource, S_IRUGO, ecard_show_resources, NULL), - __ATTR(type, S_IRUGO, ecard_show_type, NULL), - __ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL), - __ATTR_NULL, +static DEVICE_ATTR_RO(type); + +static struct attribute *ecard_dev_attrs[] = { + &dev_attr_device.attr, + &dev_attr_dma.attr, + &dev_attr_irq.attr, + &dev_attr_resource.attr, + &dev_attr_type.attr, + &dev_attr_vendor.attr, + NULL, }; - +ATTRIBUTE_GROUPS(ecard_dev); int ecard_request_resources(struct expansion_card *ec) { @@ -1120,7 +1126,7 @@ static int ecard_match(struct device *_dev, struct device_driver *_drv) struct bus_type ecard_bus_type = { .name = "ecard", - .dev_attrs = ecard_dev_attrs, + .dev_groups = ecard_dev_groups, .match = ecard_match, .probe = ecard_drv_probe, .remove = ecard_drv_remove, -- cgit From 1b8b02f0d084a2d9a966d5ae004d49c8e76aa8cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Jun 2017 14:31:21 +0200 Subject: arm: ecard: fix dev_groups patch typo Commit 71d1e5d71cec ("arm: ecard: use dev_groups and not dev_attrs for bus_type") had a typo in the resource attribute definition. Fix that up. Reported-by: kbuild test robot Fixes: 71d1e5d71cec ("arm: ecard: use dev_groups and not dev_attrs for bus_type") Cc: Russell King Cc: Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm/mach-rpc/ecard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c index f75b8b562d57..5966964222b5 100644 --- a/arch/arm/mach-rpc/ecard.c +++ b/arch/arm/mach-rpc/ecard.c @@ -789,7 +789,7 @@ static ssize_t resource_show(struct device *dev, struct device_attribute *attr, return str - buf; } -static DEVICE_ATTR_RO(resource_show) +static DEVICE_ATTR_RO(resource) static ssize_t vendor_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit From d565ed38d045793b76f022565a50793a3535bdbd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 14 Jun 2017 11:54:29 +0200 Subject: arm: mach-rpc: ecard: fix build error The last commit from me had a missing ';' which broke the build. Thanks to Arnd for pointing out the issue. Reported-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-rpc/ecard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c index 5966964222b5..bdb5ec1cf560 100644 --- a/arch/arm/mach-rpc/ecard.c +++ b/arch/arm/mach-rpc/ecard.c @@ -789,7 +789,7 @@ static ssize_t resource_show(struct device *dev, struct device_attribute *attr, return str - buf; } -static DEVICE_ATTR_RO(resource) +static DEVICE_ATTR_RO(resource); static ssize_t vendor_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit