Commit 97466841 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'driver-core-4.13-rc1' of...

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
  ...
parents 9a715cd5 d565ed38
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
What:           /sys/.../uevent
Date:           May 2017
KernelVersion:  4.13
Contact:        Linux kernel mailing list <linux-kernel@vger.kernel.org>
Description:
                Enable passing additional variables for synthetic uevents that
                are generated by writing /sys/.../uevent file.

                Recognized extended format is ACTION [UUID [KEY=VALUE ...].

                The ACTION is compulsory - it is the name of the uevent action
                ("add", "change", "remove"). There is no change compared to
                previous functionality here. The rest of the extended format
                is optional.

                You need to pass UUID first before any KEY=VALUE pairs.
                The UUID must be in "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
                format where 'x' is a hex digit. The UUID is considered to be
                a transaction identifier so it's possible to use the same UUID
                value for one or more synthetic uevents in which case we
                logically group these uevents together for any userspace
                listeners. The UUID value appears in uevent as
                "SYNTH_UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" environment
                variable.

                If UUID is not passed in, the generated synthetic uevent gains
                "SYNTH_UUID=0" environment variable automatically.

                The KEY=VALUE pairs can contain alphanumeric characters only.
                It's possible to define zero or more pairs - each pair is then
                delimited by a space character ' '. Each pair appears in
                synthetic uevent as "SYNTH_ARG_KEY=VALUE". That means the KEY
                name gains "SYNTH_ARG_" prefix to avoid possible collisions
                with existing variables.

                Example of valid sequence written to the uevent file:

                    add fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed A=1 B=abc

                This generates synthetic uevent including these variables:

                    ACTION=add
                    SYNTH_ARG_A=1
                    SYNTH_ARG_B=abc
                    SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed
Users:
                udev, userspace tools generating synthetic uevents
+2 −2
Original line number Diff line number Diff line
@@ -249,7 +249,7 @@ nodes to be present and contain the properties described below.
		Usage: Optional
		Value type: <u32>
		Definition:
			# u32 value representing CPU capacity [3] in
			# u32 value representing CPU capacity [4] in
			  DMIPS/MHz, relative to highest capacity-dmips-mhz
			  in the system.

@@ -476,5 +476,5 @@ cpus {
[2] arm/msm/qcom,kpss-acc.txt
[3] ARM Linux kernel documentation - idle states bindings
    Documentation/devicetree/bindings/arm/idle-states.txt
[3] ARM Linux kernel documentation - cpu capacity bindings
[4] ARM Linux kernel documentation - cpu capacity bindings
    Documentation/devicetree/bindings/arm/cpu-capacity.txt
+11 −0
Original line number Diff line number Diff line
@@ -44,6 +44,17 @@ request_firmware_nowait
.. kernel-doc:: drivers/base/firmware_class.c
   :functions: request_firmware_nowait

Considerations for suspend and resume
=====================================

During suspend and resume only the built-in firmware and the firmware cache
elements of the firmware API can be used. This is managed by fw_pm_notify().

fw_pm_notify
------------
.. kernel-doc:: drivers/base/firmware_class.c
   :functions: fw_pm_notify

request firmware API expected driver use
========================================

+1 −0
Original line number Diff line number Diff line
@@ -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
+6 −215
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
 * for more details.
 */

#include <linux/arch_topology.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
@@ -44,77 +45,6 @@
 * 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;
}

#ifdef CONFIG_PROC_SYSCTL
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);
#endif

#ifdef CONFIG_OF
struct cpu_efficiency {
@@ -143,145 +73,6 @@ 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 !ret;
			}
		}
		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

/*
 * Iterate all CPUs' descriptor in DT and compute the efficiency
@@ -320,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;
		}
@@ -368,8 +159,8 @@ static void __init parse_dt_topology(void)
		middle_capacity = ((max_capacity / 3)
				>> (SCHED_CAPACITY_SHIFT-1)) + 1;

	if (cap_from_dt && !cap_parsing_failed)
		normalize_cpu_capacity();
	if (cap_from_dt)
		topology_normalize_cpu_scale();
}

/*
@@ -382,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
Loading