diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-03 20:27:48 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-03 20:27:48 -0700 |
commit | 974668417b74ec5f68df2411f53b3d3812565059 (patch) | |
tree | c76be88bc72bf6b0abe8843f418e4e2518053947 /arch/arm64 | |
parent | 9a715cd54347948e74f1a597da22884af287727d (diff) | |
parent | d565ed38d045793b76f022565a50793a3535bdbd (diff) | |
download | lwn-974668417b74ec5f68df2411f53b3d3812565059.tar.gz lwn-974668417b74ec5f68df2411f53b3d3812565059.zip |
Merge tag 'driver-core-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg KH:
"Here is the big driver core update for 4.13-rc1.
The large majority of this is a lot of cleanup of old fields in the
driver core structures and their remaining usages in random drivers.
All of those fixes have been reviewed by the various subsystem
maintainers. There's also some small firmware updates in here, a new
kobject uevent api interface that makes userspace interaction easier,
and a few other minor things.
All of these have been in linux-next for a long while with no reported
issues"
* tag 'driver-core-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (56 commits)
arm: mach-rpc: ecard: fix build error
zram: convert remaining CLASS_ATTR() to CLASS_ATTR_RO()
driver-core: remove struct bus_type.dev_attrs
powerpc: vio_cmo: use dev_groups and not dev_attrs for bus_type
powerpc: vio: use dev_groups and not dev_attrs for bus_type
USB: usbip: convert to use DRIVER_ATTR_RW
s390: drivers: convert to use DRIVER_ATTR_RO/WO
platform: thinkpad_acpi: convert to use DRIVER_ATTR_RO/RW
pcmcia: ds: convert to use DRIVER_ATTR_RO
wireless: ipw2x00: convert to use DRIVER_ATTR_RW
net: ehea: convert to use DRIVER_ATTR_RO
net: caif: convert to use DRIVER_ATTR_RO
TTY: hvc: convert to use DRIVER_ATTR_RW
PCI: pci-driver: convert to use DRIVER_ATTR_WO
IB: nes: convert to use DRIVER_ATTR_RW
HID: hid-core: convert to use DRIVER_ATTR_RO and drv_groups
arm: ecard: fix dev_groups patch typo
tty: serdev: use dev_groups and not dev_attrs for bus_type
sparc: vio: use dev_groups and not dev_attrs for bus_type
hid: intel-ish-hid: use dev_groups and not dev_attrs for bus_type
...
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm64/kernel/topology.c | 226 |
2 files changed, 5 insertions, 222 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 95c7ed392003..300146dc8433 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -41,6 +41,7 @@ config ARM64 select EDAC_SUPPORT select FRAME_POINTER select GENERIC_ALLOCATOR + select GENERIC_ARCH_TOPOLOGY select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS_BROADCAST select GENERIC_CPU_AUTOPROBE diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 08243533e5ee..79244c75eaec 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -11,7 +11,7 @@ * for more details. */ -#include <linux/acpi.h> +#include <linux/arch_topology.h> #include <linux/cpu.h> #include <linux/cpumask.h> #include <linux/init.h> @@ -23,227 +23,11 @@ #include <linux/sched/topology.h> #include <linux/slab.h> #include <linux/string.h> -#include <linux/cpufreq.h> #include <asm/cpu.h> #include <asm/cputype.h> #include <asm/topology.h> -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); - -static u32 capacity_scale; -static u32 *raw_capacity; -static bool cap_parsing_failed; - -static void __init parse_cpu_capacity(struct device_node *cpu_node, int cpu) -{ - int ret; - u32 cpu_capacity; - - if (cap_parsing_failed) - return; - - 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; - } - } - 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); - } -} - -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) { - pr_debug("cpu_capacity: cpu=%d raw_capacity=%u\n", - cpu, raw_capacity[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) -{ - /* - * on ACPI-based systems we need to use the default cpu capacity - * until we have the necessary code to parse the cpu capacity, so - * skip registering cpufreq notifier. - */ - if (!acpi_disabled || 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 - static int __init get_cpu_for_node(struct device_node *node) { struct device_node *cpu_node; @@ -255,7 +39,7 @@ static int __init get_cpu_for_node(struct device_node *node) for_each_possible_cpu(cpu) { if (of_get_cpu_node(cpu, NULL) == cpu_node) { - parse_cpu_capacity(cpu_node, cpu); + topology_parse_cpu_capacity(cpu_node, cpu); of_node_put(cpu_node); return cpu; } @@ -400,16 +184,14 @@ static int __init parse_dt_topology(void) * cluster with restricted subnodes. */ map = of_get_child_by_name(cn, "cpu-map"); - if (!map) { - cap_parsing_failed = true; + if (!map) goto out; - } ret = parse_cluster(map, 0); if (ret != 0) goto out_map; - normalize_cpu_capacity(); + topology_normalize_cpu_scale(); /* * Check that all cores are in the topology; the SMP code will |