aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2024-01-08 13:26:18 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2024-01-08 13:26:18 +1100
commit7c047f5f0fc5825839d43fa1122663a455557655 (patch)
treecf62a153c1f1a532b4478966b8bf4f017b37b2d3
parent0ff56713f10add3aa110fd3b4d97d54031bafd77 (diff)
parentc312828c37a72fe2d033a961c47c227b0767e9f8 (diff)
downloadlinux-next-7c047f5f0fc5825839d43fa1122663a455557655.tar.gz
Merge branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
-rw-r--r--Documentation/ABI/testing/sysfs-firmware-initrd8
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt5
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/include/asm/cpu.h1
-rw-r--r--arch/arm64/kernel/setup.c13
-rw-r--r--arch/loongarch/Kconfig2
-rw-r--r--arch/loongarch/kernel/topology.c42
-rw-r--r--arch/riscv/Kconfig1
-rw-r--r--arch/riscv/kernel/setup.c18
-rw-r--r--arch/x86/Kconfig2
-rw-r--r--arch/x86/include/asm/cpu.h4
-rw-r--r--arch/x86/kernel/topology.c33
-rw-r--r--drivers/acpi/Kconfig1
-rw-r--r--drivers/acpi/acpi_processor.c18
-rw-r--r--drivers/acpi/property.c4
-rw-r--r--drivers/base/arch_topology.c38
-rw-r--r--drivers/base/auxiliary.c2
-rw-r--r--drivers/base/bus.c8
-rw-r--r--drivers/base/class.c1
-rw-r--r--drivers/base/container.c2
-rw-r--r--drivers/base/core.c13
-rw-r--r--drivers/base/cpu.c39
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/init.c2
-rw-r--r--drivers/base/isa.c2
-rw-r--r--drivers/base/memory.c2
-rw-r--r--drivers/base/node.c11
-rw-r--r--drivers/base/power/clock_ops.c2
-rw-r--r--drivers/base/property.c1
-rw-r--r--drivers/base/soc.c6
-rw-r--r--drivers/base/swnode.c11
-rw-r--r--drivers/edac/edac_device.h2
-rw-r--r--drivers/edac/edac_device_sysfs.c2
-rw-r--r--drivers/edac/edac_module.c4
-rw-r--r--drivers/edac/edac_pci_sysfs.c2
-rw-r--r--drivers/pmdomain/core.c2
-rw-r--r--fs/kernfs/dir.c85
-rw-r--r--fs/kernfs/file.c2
-rw-r--r--fs/kernfs/mount.c3
-rw-r--r--fs/sysfs/dir.c2
-rw-r--r--include/linux/container.h2
-rw-r--r--include/linux/cpu.h5
-rw-r--r--include/linux/device.h8
-rw-r--r--include/linux/device/bus.h2
-rw-r--r--include/linux/device/class.h2
-rw-r--r--include/linux/edac.h4
-rw-r--r--include/linux/pm_clock.h4
-rw-r--r--include/linux/property.h26
-rw-r--r--init/initramfs.c18
-rw-r--r--kernel/cgroup/cgroup-v1.c2
-rw-r--r--kernel/cgroup/cgroup.c35
-rw-r--r--kernel/cgroup/cpuset.c2
52 files changed, 246 insertions, 263 deletions
diff --git a/Documentation/ABI/testing/sysfs-firmware-initrd b/Documentation/ABI/testing/sysfs-firmware-initrd
new file mode 100644
index 00000000000000..20bf7cf77a1910
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-firmware-initrd
@@ -0,0 +1,8 @@
+What: /sys/firmware/initrd
+Date: December 2023
+Contact: Alexander Graf <graf@amazon.com>
+Description:
+ When the kernel was booted with an initrd and the
+ "retain_initrd" option is set on the kernel command
+ line, /sys/firmware/initrd contains the contents of the
+ initrd that the kernel was booted with.
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index a36cf8cc582c1a..4ef41092bb668e 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2449,7 +2449,7 @@
between unregistering the boot console and initializing
the real console.
- keepinitrd [HW,ARM]
+ keepinitrd [HW,ARM] See retain_initrd.
kernelcore= [KNL,X86,IA-64,PPC]
Format: nn[KMGTPE] | nn% | "mirror"
@@ -5604,7 +5604,8 @@
Useful for devices that are detected asynchronously
(e.g. USB and MMC devices).
- retain_initrd [RAM] Keep initrd memory after extraction
+ retain_initrd [RAM] Keep initrd memory after extraction. After boot, it will
+ be accessible via /sys/firmware/initrd.
retbleed= [X86] Control mitigation of RETBleed (Arbitrary
Speculative Code Execution with Return Instructions)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c5321223ac67ba..35527c32b1a004 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -133,6 +133,7 @@ config ARM64
select GENERIC_ARCH_TOPOLOGY
select GENERIC_CLOCKEVENTS_BROADCAST
select GENERIC_CPU_AUTOPROBE
+ select GENERIC_CPU_DEVICES
select GENERIC_CPU_VULNERABILITIES
select GENERIC_EARLY_IOREMAP
select GENERIC_IDLE_POLL_SETUP
diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
index f3034099fd952b..b1e43f56ee461e 100644
--- a/arch/arm64/include/asm/cpu.h
+++ b/arch/arm64/include/asm/cpu.h
@@ -38,7 +38,6 @@ struct cpuinfo_32bit {
};
struct cpuinfo_arm64 {
- struct cpu cpu;
struct kobject kobj;
u64 reg_ctr;
u64 reg_cntfrq;
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 417a8a86b2db59..42c690bb2d608c 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -402,19 +402,10 @@ static inline bool cpu_can_disable(unsigned int cpu)
return false;
}
-static int __init topology_init(void)
+bool arch_cpu_is_hotpluggable(int num)
{
- int i;
-
- for_each_possible_cpu(i) {
- struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
- cpu->hotpluggable = cpu_can_disable(i);
- register_cpu(cpu, i);
- }
-
- return 0;
+ return cpu_can_disable(num);
}
-subsys_initcall(topology_init);
static void dump_kernel_offset(void)
{
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index ee123820a4760a..15d05dd2b7f3de 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -5,6 +5,7 @@ config LOONGARCH
select ACPI
select ACPI_GENERIC_GSI if ACPI
select ACPI_MCFG if ACPI
+ select ACPI_HOTPLUG_CPU if ACPI_PROCESSOR && HOTPLUG_CPU
select ACPI_PPTT if ACPI
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
select ARCH_BINFMT_ELF_STATE
@@ -71,6 +72,7 @@ config LOONGARCH
select GENERIC_CLOCKEVENTS
select GENERIC_CMOS_UPDATE
select GENERIC_CPU_AUTOPROBE
+ select GENERIC_CPU_DEVICES
select GENERIC_ENTRY
select GENERIC_GETTIMEOFDAY
select GENERIC_IOREMAP if !ARCH_IOREMAP
diff --git a/arch/loongarch/kernel/topology.c b/arch/loongarch/kernel/topology.c
index 3fd1660066983b..75d5c51a7cd3de 100644
--- a/arch/loongarch/kernel/topology.c
+++ b/arch/loongarch/kernel/topology.c
@@ -10,47 +10,9 @@
#include <acpi/processor.h>
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
-
#ifdef CONFIG_HOTPLUG_CPU
-int arch_register_cpu(int cpu)
+bool arch_cpu_is_hotpluggable(int cpu)
{
- int ret;
- struct cpu *c = &per_cpu(cpu_devices, cpu);
-
- c->hotpluggable = 1;
- ret = register_cpu(c, cpu);
- if (ret < 0)
- pr_warn("register_cpu %d failed (%d)\n", cpu, ret);
-
- return ret;
-}
-EXPORT_SYMBOL(arch_register_cpu);
-
-void arch_unregister_cpu(int cpu)
-{
- struct cpu *c = &per_cpu(cpu_devices, cpu);
-
- c->hotpluggable = 0;
- unregister_cpu(c);
+ return !io_master(cpu);
}
-EXPORT_SYMBOL(arch_unregister_cpu);
#endif
-
-static int __init topology_init(void)
-{
- int i, ret;
-
- for_each_present_cpu(i) {
- struct cpu *c = &per_cpu(cpu_devices, i);
-
- c->hotpluggable = !io_master(i);
- ret = register_cpu(c, i);
- if (ret < 0)
- pr_warn("topology_init: register_cpu %d failed (%d)\n", i, ret);
- }
-
- return 0;
-}
-
-subsys_initcall(topology_init);
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index ba6d1c8a1eec33..6047e44e1e0663 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -72,6 +72,7 @@ config RISCV
select GENERIC_ARCH_TOPOLOGY
select GENERIC_ATOMIC64 if !64BIT
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+ select GENERIC_CPU_DEVICES
select GENERIC_EARLY_IOREMAP
select GENERIC_ENTRY
select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 2bf88280462440..4f73c0ae44b25d 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -50,7 +50,6 @@ atomic_t hart_lottery __section(".sdata")
#endif
;
unsigned long boot_cpu_hartid;
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
/*
* Place kernel memory regions on the resource tree so that
@@ -298,23 +297,10 @@ void __init setup_arch(char **cmdline_p)
riscv_user_isa_enable();
}
-static int __init topology_init(void)
+bool arch_cpu_is_hotpluggable(int cpu)
{
- int i, ret;
-
- for_each_possible_cpu(i) {
- struct cpu *cpu = &per_cpu(cpu_devices, i);
-
- cpu->hotpluggable = cpu_has_hotplug(i);
- ret = register_cpu(cpu, i);
- if (unlikely(ret))
- pr_warn("Warning: %s: register_cpu %d failed (%d)\n",
- __func__, i, ret);
- }
-
- return 0;
+ return cpu_has_hotplug(cpu);
}
-subsys_initcall(topology_init);
void free_initmem(void)
{
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e07d24052bcb6b..c0f45c0079972f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -59,6 +59,7 @@ config X86
#
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
+ select ACPI_HOTPLUG_CPU if ACPI_PROCESSOR && HOTPLUG_CPU
select ARCH_32BIT_OFF_T if X86_32
select ARCH_CLOCKSOURCE_INIT
select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
@@ -149,6 +150,7 @@ config X86
select GENERIC_CLOCKEVENTS_MIN_ADJUST
select GENERIC_CMOS_UPDATE
select GENERIC_CPU_AUTOPROBE
+ select GENERIC_CPU_DEVICES
select GENERIC_CPU_VULNERABILITIES
select GENERIC_EARLY_IOREMAP
select GENERIC_ENTRY
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index fecc4fe1d68aff..f8f9a9b7939587 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -23,10 +23,6 @@ static inline void prefill_possible_map(void) {}
#endif /* CONFIG_SMP */
-struct x86_cpu {
- struct cpu cpu;
-};
-
#ifdef CONFIG_HOTPLUG_CPU
extern void soft_restart_cpu(void);
#endif
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index 0bab0313003362..d42c28b8bfd80c 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -35,38 +35,9 @@
#include <asm/io_apic.h>
#include <asm/cpu.h>
-static DEFINE_PER_CPU(struct x86_cpu, cpu_devices);
-
#ifdef CONFIG_HOTPLUG_CPU
-int arch_register_cpu(int cpu)
+bool arch_cpu_is_hotpluggable(int cpu)
{
- struct x86_cpu *xc = per_cpu_ptr(&cpu_devices, cpu);
-
- xc->cpu.hotpluggable = cpu > 0;
- return register_cpu(&xc->cpu, cpu);
-}
-EXPORT_SYMBOL(arch_register_cpu);
-
-void arch_unregister_cpu(int num)
-{
- unregister_cpu(&per_cpu(cpu_devices, num).cpu);
-}
-EXPORT_SYMBOL(arch_unregister_cpu);
-#else /* CONFIG_HOTPLUG_CPU */
-
-int __init arch_register_cpu(int num)
-{
- return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
+ return cpu > 0;
}
#endif /* CONFIG_HOTPLUG_CPU */
-
-static int __init topology_init(void)
-{
- int i;
-
- for_each_present_cpu(i)
- arch_register_cpu(i);
-
- return 0;
-}
-subsys_initcall(topology_init);
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 6f2bfcf7645ce6..3c3f8037ebeddd 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -314,7 +314,6 @@ config ACPI_HOTPLUG_CPU
bool
depends on ACPI_PROCESSOR && HOTPLUG_CPU
select ACPI_CONTAINER
- default y
config ACPI_PROCESSOR_AGGREGATOR
tristate "Processor Aggregator"
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index 0f5218e361df5c..4fe2ef54088c65 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -184,24 +184,6 @@ static void __init acpi_pcc_cpufreq_init(void) {}
/* Initialization */
#ifdef CONFIG_ACPI_HOTPLUG_CPU
-int __weak acpi_map_cpu(acpi_handle handle,
- phys_cpuid_t physid, u32 acpi_id, int *pcpu)
-{
- return -ENODEV;
-}
-
-int __weak acpi_unmap_cpu(int cpu)
-{
- return -ENODEV;
-}
-
-int __weak arch_register_cpu(int cpu)
-{
- return -ENODEV;
-}
-
-void __weak arch_unregister_cpu(int cpu) {}
-
static int acpi_processor_hotadd_init(struct acpi_processor *pr)
{
unsigned long long sta;
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 07d76fb740b6d6..a6ead5204046b1 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -881,6 +881,7 @@ static struct fwnode_handle *acpi_parse_string_ref(const struct fwnode_handle *f
* @index: Index of the reference to return
* @num_args: Maximum number of arguments after each reference
* @args: Location to store the returned reference with optional arguments
+ * (may be NULL)
*
* Find property with @name, verifify that it is a package containing at least
* one object reference and if so, store the ACPI device object pointer to the
@@ -938,6 +939,9 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
if (!device)
return -EINVAL;
+ if (!args)
+ return 0;
+
args->fwnode = acpi_fwnode_handle(device);
args->nargs = 0;
diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index 5aaa0865625d0d..018ac202de345e 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -219,20 +219,34 @@ static DECLARE_WORK(update_topology_flags_work, update_topology_flags_workfn);
static DEVICE_ATTR_RO(cpu_capacity);
-static int register_cpu_capacity_sysctl(void)
+static int cpu_capacity_sysctl_add(unsigned int cpu)
{
- int i;
- struct device *cpu;
+ struct device *cpu_dev = get_cpu_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);
- }
+ if (!cpu_dev)
+ return -ENOENT;
+
+ device_create_file(cpu_dev, &dev_attr_cpu_capacity);
+
+ return 0;
+}
+
+static int cpu_capacity_sysctl_remove(unsigned int cpu)
+{
+ struct device *cpu_dev = get_cpu_device(cpu);
+
+ if (!cpu_dev)
+ return -ENOENT;
+
+ device_remove_file(cpu_dev, &dev_attr_cpu_capacity);
+
+ return 0;
+}
+
+static int register_cpu_capacity_sysctl(void)
+{
+ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "topology/cpu-capacity",
+ cpu_capacity_sysctl_add, cpu_capacity_sysctl_remove);
return 0;
}
diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c
index 4d4c2c8d26c480..d3a2c40c2f1272 100644
--- a/drivers/base/auxiliary.c
+++ b/drivers/base/auxiliary.c
@@ -244,7 +244,7 @@ static void auxiliary_bus_shutdown(struct device *dev)
auxdrv->shutdown(auxdev);
}
-static struct bus_type auxiliary_bus_type = {
+static const struct bus_type auxiliary_bus_type = {
.name = "auxiliary",
.probe = auxiliary_bus_probe,
.remove = auxiliary_bus_remove,
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 84a21084d67d16..daee55c9b2d9e1 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -1030,7 +1030,7 @@ static void device_insertion_sort_klist(struct device *a, struct list_head *list
list_move_tail(&a->p->knode_bus.n_node, list);
}
-void bus_sort_breadthfirst(struct bus_type *bus,
+void bus_sort_breadthfirst(const struct bus_type *bus,
int (*compare)(const struct device *a,
const struct device *b))
{
@@ -1194,7 +1194,7 @@ static void system_root_device_release(struct device *dev)
kfree(dev);
}
-static int subsys_register(struct bus_type *subsys,
+static int subsys_register(const struct bus_type *subsys,
const struct attribute_group **groups,
struct kobject *parent_of_root)
{
@@ -1264,7 +1264,7 @@ err_sp:
* directory itself and not some create fake root-device placed in
* /sys/devices/system/<name>.
*/
-int subsys_system_register(struct bus_type *subsys,
+int subsys_system_register(const struct bus_type *subsys,
const struct attribute_group **groups)
{
return subsys_register(subsys, groups, &system_kset->kobj);
@@ -1282,7 +1282,7 @@ EXPORT_SYMBOL_GPL(subsys_system_register);
* There's no restriction on device naming. This is for kernel software
* constructs which need sysfs interface.
*/
-int subsys_virtual_register(struct bus_type *subsys,
+int subsys_virtual_register(const struct bus_type *subsys,
const struct attribute_group **groups)
{
struct kobject *virtual_dir;
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 7e78aee0fd6c39..7b38fdf8e1d78e 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -213,6 +213,7 @@ int class_register(const struct class *cls)
return 0;
err_out:
+ lockdep_unregister_key(key);
kfree(cp);
return error;
}
diff --git a/drivers/base/container.c b/drivers/base/container.c
index 1ba42d2d353223..f40588ebc3f557 100644
--- a/drivers/base/container.c
+++ b/drivers/base/container.c
@@ -24,7 +24,7 @@ static int container_offline(struct device *dev)
return cdev->offline ? cdev->offline(cdev) : 0;
}
-struct bus_type container_subsys = {
+const struct bus_type container_subsys = {
.name = CONTAINER_BUS_NAME,
.dev_name = CONTAINER_BUS_NAME,
.online = trivial_online,
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 67ba592afc7776..14d46af40f9a15 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -298,7 +298,7 @@ static inline bool device_link_flag_is_sync_state_only(u32 flags)
* Check if @target depends on @dev or any device dependent on it (its child or
* its consumer etc). Return 1 if that is the case or 0 otherwise.
*/
-int device_is_dependent(struct device *dev, void *target)
+static int device_is_dependent(struct device *dev, void *target)
{
struct device_link *link;
int ret;
@@ -1641,7 +1641,7 @@ static void device_links_purge(struct device *dev)
#define FW_DEVLINK_FLAGS_RPM (FW_DEVLINK_FLAGS_ON | \
DL_FLAG_PM_RUNTIME)
-static u32 fw_devlink_flags = FW_DEVLINK_FLAGS_ON;
+static u32 fw_devlink_flags = FW_DEVLINK_FLAGS_RPM;
static int __init fw_devlink_setup(char *arg)
{
if (!arg)
@@ -4944,13 +4944,14 @@ define_dev_printk_level(_dev_info, KERN_INFO);
*
* return dev_err_probe(dev, err, ...);
*
- * Note that it is deemed acceptable to use this function for error
- * prints during probe even if the @err is known to never be -EPROBE_DEFER.
+ * Using this helper in your probe function is totally fine even if @err is
+ * known to never be -EPROBE_DEFER.
* The benefit compared to a normal dev_err() is the standardized format
- * of the error code and the fact that the error code is returned.
+ * of the error code, it being emitted symbolically (i.e. you get "EAGAIN"
+ * instead of "-35") and the fact that the error code is returned which allows
+ * more compact error paths.
*
* Returns @err.
- *
*/
int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
{
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 548491de818ef1..47de0f140ba65e 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -525,19 +525,42 @@ bool cpu_is_hotpluggable(unsigned int cpu)
EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
#ifdef CONFIG_GENERIC_CPU_DEVICES
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
-#endif
+DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+bool __weak arch_cpu_is_hotpluggable(int cpu)
+{
+ return false;
+}
+
+int __weak arch_register_cpu(int cpu)
+{
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+ c->hotpluggable = arch_cpu_is_hotpluggable(cpu);
+
+ return register_cpu(c, cpu);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+void __weak arch_unregister_cpu(int num)
+{
+ unregister_cpu(&per_cpu(cpu_devices, num));
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+#endif /* CONFIG_GENERIC_CPU_DEVICES */
static void __init cpu_dev_register_generic(void)
{
-#ifdef CONFIG_GENERIC_CPU_DEVICES
- int i;
+ int i, ret;
- for_each_possible_cpu(i) {
- if (register_cpu(&per_cpu(cpu_devices, i), i))
- panic("Failed to register CPU device");
+ if (!IS_ENABLED(CONFIG_GENERIC_CPU_DEVICES))
+ return;
+
+ for_each_present_cpu(i) {
+ ret = arch_register_cpu(i);
+ if (ret)
+ pr_warn("register_cpu %d failed (%d)\n", i, ret);
}
-#endif
}
#ifdef CONFIG_GENERIC_CPU_VULNERABILITIES
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 0c3725c3eefa46..85152537dbf12d 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -313,7 +313,7 @@ static void deferred_probe_timeout_work_func(struct work_struct *work)
mutex_lock(&deferred_probe_mutex);
list_for_each_entry(p, &deferred_probe_pending_list, deferred_probe)
- dev_info(p->device, "deferred probe pending\n");
+ dev_info(p->device, "deferred probe pending: %s", p->deferred_probe_reason ?: "(reason unknown)\n");
mutex_unlock(&deferred_probe_mutex);
fw_devlink_probing_done();
diff --git a/drivers/base/init.c b/drivers/base/init.c
index 397eb9880cecb8..c4954835128cfe 100644
--- a/drivers/base/init.c
+++ b/drivers/base/init.c
@@ -35,8 +35,8 @@ void __init driver_init(void)
of_core_init();
platform_bus_init();
auxiliary_bus_init();
- cpu_dev_init();
memory_dev_init();
node_dev_init();
+ cpu_dev_init();
container_dev_init();
}
diff --git a/drivers/base/isa.c b/drivers/base/isa.c
index 675ad313922462..e23d0b49a79345 100644
--- a/drivers/base/isa.c
+++ b/drivers/base/isa.c
@@ -82,7 +82,7 @@ static int isa_bus_resume(struct device *dev)
return 0;
}
-static struct bus_type isa_bus_type = {
+static const struct bus_type isa_bus_type = {
.name = "isa",
.match = isa_bus_match,
.probe = isa_bus_probe,
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 8a13babd826ce3..14f964a7719bd0 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -68,7 +68,7 @@ static inline unsigned long phys_to_block_id(unsigned long phys)
static int memory_subsys_online(struct device *dev);
static int memory_subsys_offline(struct device *dev);
-static struct bus_type memory_subsys = {
+static const struct bus_type memory_subsys = {
.name = MEMORY_CLASS_NAME,
.dev_name = MEMORY_CLASS_NAME,
.online = memory_subsys_online,
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 493d533f837556..433897eecbdcc9 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -21,7 +21,7 @@
#include <linux/swap.h>
#include <linux/slab.h>
-static struct bus_type node_subsys = {
+static const struct bus_type node_subsys = {
.name = "node",
.dev_name = "node",
};
@@ -868,11 +868,15 @@ int __register_one_node(int nid)
{
int error;
int cpu;
+ struct node *node;
- node_devices[nid] = kzalloc(sizeof(struct node), GFP_KERNEL);
- if (!node_devices[nid])
+ node = kzalloc(sizeof(struct node), GFP_KERNEL);
+ if (!node)
return -ENOMEM;
+ INIT_LIST_HEAD(&node->access_list);
+ node_devices[nid] = node;
+
error = register_node(node_devices[nid], nid);
/* link cpu under this node */
@@ -881,7 +885,6 @@ int __register_one_node(int nid)
register_cpu_under_node(cpu, nid);
}
- INIT_LIST_HEAD(&node_devices[nid]->access_list);
node_init_caches(nid);
return error;
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 4110c19c08dcd7..e18ba676cdf645 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -793,7 +793,7 @@ static int pm_clk_notify(struct notifier_block *nb,
* the remaining members of @clknb should be populated prior to calling this
* routine.
*/
-void pm_clk_add_notifier(struct bus_type *bus,
+void pm_clk_add_notifier(const struct bus_type *bus,
struct pm_clk_notifier_block *clknb)
{
if (!bus || !clknb)
diff --git a/drivers/base/property.c b/drivers/base/property.c
index b79608ee0b46be..f20379c9a5c904 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -508,6 +508,7 @@ EXPORT_SYMBOL_GPL(fwnode_property_match_string);
* @nargs: Number of arguments. Ignored if @nargs_prop is non-NULL.
* @index: Index of the reference, from zero onwards.
* @args: Result structure with reference and integer arguments.
+ * May be NULL.
*
* Obtain a reference based on a named property in an fwnode, with
* integer arguments.
diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index 8dec5228fde3d4..282c38aece0de8 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -28,7 +28,7 @@ struct soc_device {
int soc_dev_num;
};
-static struct bus_type soc_bus_type = {
+static const struct bus_type soc_bus_type = {
.name = "soc",
};
static bool soc_bus_registered;
@@ -106,7 +106,7 @@ static void soc_release(struct device *dev)
{
struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
- ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
+ ida_free(&soc_ida, soc_dev->soc_dev_num);
kfree(soc_dev->dev.groups);
kfree(soc_dev);
}
@@ -155,7 +155,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
soc_attr_groups[1] = soc_dev_attr->custom_attr_group;
/* Fetch a unique (reclaimable) SOC ID. */
- ret = ida_simple_get(&soc_ida, 0, 0, GFP_KERNEL);
+ ret = ida_alloc(&soc_ida, GFP_KERNEL);
if (ret < 0)
goto out3;
soc_dev->soc_dev_num = ret;
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 1886995a0b3a30..36512fb75a201c 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -541,6 +541,9 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
if (nargs > NR_FWNODE_REFERENCE_ARGS)
return -EINVAL;
+ if (!args)
+ return 0;
+
args->fwnode = software_node_get(refnode);
args->nargs = nargs;
@@ -747,10 +750,10 @@ static void software_node_release(struct kobject *kobj)
struct swnode *swnode = kobj_to_swnode(kobj);
if (swnode->parent) {
- ida_simple_remove(&swnode->parent->child_ids, swnode->id);
+ ida_free(&swnode->parent->child_ids, swnode->id);
list_del(&swnode->entry);
} else {
- ida_simple_remove(&swnode_root_ids, swnode->id);
+ ida_free(&swnode_root_ids, swnode->id);
}
if (swnode->allocated)
@@ -776,8 +779,8 @@ swnode_register(const struct software_node *node, struct swnode *parent,
if (!swnode)
return ERR_PTR(-ENOMEM);
- ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids,
- 0, 0, GFP_KERNEL);
+ ret = ida_alloc(parent ? &parent->child_ids : &swnode_root_ids,
+ GFP_KERNEL);
if (ret < 0) {
kfree(swnode);
return ERR_PTR(ret);
diff --git a/drivers/edac/edac_device.h b/drivers/edac/edac_device.h
index 3f44e6b9d387f9..7db22a4c83ef3f 100644
--- a/drivers/edac/edac_device.h
+++ b/drivers/edac/edac_device.h
@@ -176,7 +176,7 @@ struct edac_device_ctl_info {
struct edac_dev_sysfs_attribute *sysfs_attributes;
/* pointer to main 'edac' subsys in sysfs */
- struct bus_type *edac_subsys;
+ const struct bus_type *edac_subsys;
/* the internal state of this controller instance */
int op_state;
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
index 010c26be58464d..237a542e045a3f 100644
--- a/drivers/edac/edac_device_sysfs.c
+++ b/drivers/edac/edac_device_sysfs.c
@@ -229,7 +229,7 @@ static struct kobj_type ktype_device_ctrl = {
int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
{
struct device *dev_root;
- struct bus_type *edac_subsys;
+ const struct bus_type *edac_subsys;
int err = -ENODEV;
edac_dbg(1, "\n");
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
index 32a931d0cb71ff..1c9f623826665b 100644
--- a/drivers/edac/edac_module.c
+++ b/drivers/edac/edac_module.c
@@ -67,7 +67,7 @@ char *edac_op_state_to_string(int opstate)
* sysfs object: /sys/devices/system/edac
* need to export to other files
*/
-static struct bus_type edac_subsys = {
+static const struct bus_type edac_subsys = {
.name = "edac",
.dev_name = "edac",
};
@@ -90,7 +90,7 @@ static void edac_subsys_exit(void)
}
/* return pointer to the 'edac' node in sysfs */
-struct bus_type *edac_get_sysfs_subsys(void)
+const struct bus_type *edac_get_sysfs_subsys(void)
{
return &edac_subsys;
}
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index 901d4cd3ca3876..7b44afcf48db06 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -338,7 +338,7 @@ static struct kobj_type ktype_edac_pci_main_kobj = {
static int edac_pci_main_kobj_setup(void)
{
int err = -ENODEV;
- struct bus_type *edac_subsys;
+ const struct bus_type *edac_subsys;
struct device *dev_root;
edac_dbg(0, "\n");
diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
index 9ee1bf2ece10ff..a1f6cba3ae6c86 100644
--- a/drivers/pmdomain/core.c
+++ b/drivers/pmdomain/core.c
@@ -2668,7 +2668,7 @@ static void genpd_release_dev(struct device *dev)
kfree(dev);
}
-static struct bus_type genpd_bus_type = {
+static const struct bus_type genpd_bus_type = {
.name = "genpd",
};
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 8b2bd65d70e725..a62960fdf73f08 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -27,7 +27,7 @@ static DEFINE_RWLOCK(kernfs_rename_lock); /* kn->parent and ->name */
*/
static DEFINE_SPINLOCK(kernfs_pr_cont_lock);
static char kernfs_pr_cont_buf[PATH_MAX]; /* protected by pr_cont_lock */
-static DEFINE_SPINLOCK(kernfs_idr_lock); /* root->ino_idr */
+static DEFINE_RAW_SPINLOCK(kernfs_idr_lock); /* root->ino_idr */
#define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb)
@@ -54,9 +54,9 @@ static bool kernfs_lockdep(struct kernfs_node *kn)
static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen)
{
if (!kn)
- return strlcpy(buf, "(null)", buflen);
+ return strscpy(buf, "(null)", buflen);
- return strlcpy(buf, kn->parent ? kn->name : "/", buflen);
+ return strscpy(buf, kn->parent ? kn->name : "/", buflen);
}
/* kernfs_node_depth - compute depth from @from to @to */
@@ -127,7 +127,7 @@ static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a,
*
* [3] when @kn_to is %NULL result will be "(null)"
*
- * Return: the length of the full path. If the full length is equal to or
+ * Return: the length of the constructed path. If the path would have been
* greater than @buflen, @buf contains the truncated path with the trailing
* '\0'. On error, -errno is returned.
*/
@@ -138,16 +138,17 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
struct kernfs_node *kn, *common;
const char parent_str[] = "/..";
size_t depth_from, depth_to, len = 0;
+ ssize_t copied;
int i, j;
if (!kn_to)
- return strlcpy(buf, "(null)", buflen);
+ return strscpy(buf, "(null)", buflen);
if (!kn_from)
kn_from = kernfs_root(kn_to)->kn;
if (kn_from == kn_to)
- return strlcpy(buf, "/", buflen);
+ return strscpy(buf, "/", buflen);
common = kernfs_common_ancestor(kn_from, kn_to);
if (WARN_ON(!common))
@@ -158,18 +159,19 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
buf[0] = '\0';
- for (i = 0; i < depth_from; i++)
- len += strlcpy(buf + len, parent_str,
- len < buflen ? buflen - len : 0);
+ for (i = 0; i < depth_from; i++) {
+ copied = strscpy(buf + len, parent_str, buflen - len);
+ if (copied < 0)
+ return copied;
+ len += copied;
+ }
/* Calculate how many bytes we need for the rest */
for (i = depth_to - 1; i >= 0; i--) {
for (kn = kn_to, j = 0; j < i; j++)
kn = kn->parent;
- len += strlcpy(buf + len, "/",
- len < buflen ? buflen - len : 0);
- len += strlcpy(buf + len, kn->name,
- len < buflen ? buflen - len : 0);
+
+ len += scnprintf(buf + len, buflen - len, "/%s", kn->name);
}
return len;
@@ -182,12 +184,12 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
* @buflen: size of @buf
*
* Copies the name of @kn into @buf of @buflen bytes. The behavior is
- * similar to strlcpy().
+ * similar to strscpy().
*
* Fills buffer with "(null)" if @kn is %NULL.
*
- * Return: the length of @kn's name and if @buf isn't long enough,
- * it's filled up to @buflen-1 and nul terminated.
+ * Return: the resulting length of @buf. If @buf isn't long enough,
+ * it's filled up to @buflen-1 and nul terminated, and returns -E2BIG.
*
* This function can be called from any context.
*/
@@ -214,7 +216,7 @@ int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
* path (which includes '..'s) as needed to reach from @from to @to is
* returned.
*
- * Return: the length of the full path. If the full length is equal to or
+ * Return: the length of the constructed path. If the path would have been
* greater than @buflen, @buf contains the truncated path with the trailing
* '\0'. On error, -errno is returned.
*/
@@ -265,12 +267,10 @@ void pr_cont_kernfs_path(struct kernfs_node *kn)
sz = kernfs_path_from_node(kn, NULL, kernfs_pr_cont_buf,
sizeof(kernfs_pr_cont_buf));
if (sz < 0) {
- pr_cont("(error)");
- goto out;
- }
-
- if (sz >= sizeof(kernfs_pr_cont_buf)) {
- pr_cont("(name too long)");
+ if (sz == -E2BIG)
+ pr_cont("(name too long)");
+ else
+ pr_cont("(error)");
goto out;
}
@@ -539,6 +539,7 @@ void kernfs_put(struct kernfs_node *kn)
{
struct kernfs_node *parent;
struct kernfs_root *root;
+ unsigned long flags;
if (!kn || !atomic_dec_and_test(&kn->count))
return;
@@ -563,9 +564,9 @@ void kernfs_put(struct kernfs_node *kn)
simple_xattrs_free(&kn->iattr->xattrs, NULL);
kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
}
- spin_lock(&kernfs_idr_lock);
+ raw_spin_lock_irqsave(&kernfs_idr_lock, flags);
idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
- spin_unlock(&kernfs_idr_lock);
+ raw_spin_unlock_irqrestore(&kernfs_idr_lock, flags);
kmem_cache_free(kernfs_node_cache, kn);
kn = parent;
@@ -607,6 +608,7 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
struct kernfs_node *kn;
u32 id_highbits;
int ret;
+ unsigned long irqflags;
name = kstrdup_const(name, GFP_KERNEL);
if (!name)
@@ -617,13 +619,13 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
goto err_out1;
idr_preload(GFP_KERNEL);
- spin_lock(&kernfs_idr_lock);
+ raw_spin_lock_irqsave(&kernfs_idr_lock, irqflags);
ret = idr_alloc_cyclic(&root->ino_idr, kn, 1, 0, GFP_ATOMIC);
if (ret >= 0 && ret < root->last_id_lowbits)
root->id_highbits++;
id_highbits = root->id_highbits;
root->last_id_lowbits = ret;
- spin_unlock(&kernfs_idr_lock);
+ raw_spin_unlock_irqrestore(&kernfs_idr_lock, irqflags);
idr_preload_end();
if (ret < 0)
goto err_out2;
@@ -659,9 +661,9 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
return kn;
err_out3:
- spin_lock(&kernfs_idr_lock);
+ raw_spin_lock_irqsave(&kernfs_idr_lock, irqflags);
idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
- spin_unlock(&kernfs_idr_lock);
+ raw_spin_unlock_irqrestore(&kernfs_idr_lock, irqflags);
err_out2:
kmem_cache_free(kernfs_node_cache, kn);
err_out1:
@@ -676,6 +678,18 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
{
struct kernfs_node *kn;
+ if (parent->mode & S_ISGID) {
+ /* this code block imitates inode_init_owner() for
+ * kernfs
+ */
+
+ if (parent->iattr)
+ gid = parent->iattr->ia_gid;
+
+ if (flags & KERNFS_DIR)
+ mode |= S_ISGID;
+ }
+
kn = __kernfs_new_node(kernfs_root(parent), parent,
name, mode, uid, gid, flags);
if (kn) {
@@ -702,8 +716,9 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root,
struct kernfs_node *kn;
ino_t ino = kernfs_id_ino(id);
u32 gen = kernfs_id_gen(id);
+ unsigned long flags;
- spin_lock(&kernfs_idr_lock);
+ raw_spin_lock_irqsave(&kernfs_idr_lock, flags);
kn = idr_find(&root->ino_idr, (u32)ino);
if (!kn)
@@ -727,10 +742,10 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root,
if (unlikely(!__kernfs_active(kn) || !atomic_inc_not_zero(&kn->count)))
goto err_unlock;
- spin_unlock(&kernfs_idr_lock);
+ raw_spin_unlock_irqrestore(&kernfs_idr_lock, flags);
return kn;
err_unlock:
- spin_unlock(&kernfs_idr_lock);
+ raw_spin_unlock_irqrestore(&kernfs_idr_lock, flags);
return NULL;
}
@@ -850,16 +865,16 @@ static struct kernfs_node *kernfs_walk_ns(struct kernfs_node *parent,
const unsigned char *path,
const void *ns)
{
- size_t len;
+ ssize_t len;
char *p, *name;
lockdep_assert_held_read(&kernfs_root(parent)->kernfs_rwsem);
spin_lock_irq(&kernfs_pr_cont_lock);
- len = strlcpy(kernfs_pr_cont_buf, path, sizeof(kernfs_pr_cont_buf));
+ len = strscpy(kernfs_pr_cont_buf, path, sizeof(kernfs_pr_cont_buf));
- if (len >= sizeof(kernfs_pr_cont_buf)) {
+ if (len < 0) {
spin_unlock_irq(&kernfs_pr_cont_lock);
return NULL;
}
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index f0cb729e9a9781..ffa4565c275a7a 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -447,7 +447,7 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma)
* warnings and we don't want to add spurious locking dependency
* between the two. Check whether mmap is actually implemented
* without grabbing @of->mutex by testing HAS_MMAP flag. See the
- * comment in kernfs_file_open() for more details.
+ * comment in kernfs_fop_open() for more details.
*/
if (!(of->kn->flags & KERNFS_HAS_MMAP))
return -ENODEV;
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index 4628edde2e7e1a..0c93cad0f0acac 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -125,9 +125,6 @@ static struct dentry *__kernfs_fh_to_dentry(struct super_block *sb,
inode = kernfs_get_inode(sb, kn);
kernfs_put(kn);
- if (!inode)
- return ERR_PTR(-ESTALE);
-
return d_obtain_alias(inode);
}
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index b6b6796e16160d..4df2afa551dc6f 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -81,7 +81,7 @@ void sysfs_remove_dir(struct kobject *kobj)
struct kernfs_node *kn = kobj->sd;
/*
- * In general, kboject owner is responsible for ensuring removal
+ * In general, kobject owner is responsible for ensuring removal
* doesn't race with other operations and sysfs doesn't provide any
* protection; however, when @kobj is used as a symlink target, the
* symlinking entity usually doesn't own @kobj and thus has no
diff --git a/include/linux/container.h b/include/linux/container.h
index 2566a1baa736a2..dd00cc918a926e 100644
--- a/include/linux/container.h
+++ b/include/linux/container.h
@@ -12,7 +12,7 @@
#include <linux/device.h>
/* drivers/base/power/container.c */
-extern struct bus_type container_subsys;
+extern const struct bus_type container_subsys;
struct container_dev {
struct device dev;
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index fc8094419084f6..dcb89c9871640f 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -80,6 +80,7 @@ extern __printf(4, 5)
struct device *cpu_device_create(struct device *parent, void *drvdata,
const struct attribute_group **groups,
const char *fmt, ...);
+extern bool arch_cpu_is_hotpluggable(int cpu);
extern int arch_register_cpu(int cpu);
extern void arch_unregister_cpu(int cpu);
#ifdef CONFIG_HOTPLUG_CPU
@@ -88,6 +89,10 @@ extern ssize_t arch_cpu_probe(const char *, size_t);
extern ssize_t arch_cpu_release(const char *, size_t);
#endif
+#ifdef CONFIG_GENERIC_CPU_DEVICES
+DECLARE_PER_CPU(struct cpu, cpu_devices);
+#endif
+
/*
* These states are not related to the core CPU hotplug mechanism. They are
* used by various (sub)architectures to track internal state
diff --git a/include/linux/device.h b/include/linux/device.h
index bd05b2c35e99be..97c4b046c09d94 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -62,7 +62,7 @@ struct msi_device_data;
*/
struct subsys_interface {
const char *name;
- struct bus_type *subsys;
+ const struct bus_type *subsys;
struct list_head node;
int (*add_dev)(struct device *dev, struct subsys_interface *sif);
void (*remove_dev)(struct device *dev, struct subsys_interface *sif);
@@ -71,9 +71,9 @@ struct subsys_interface {
int subsys_interface_register(struct subsys_interface *sif);
void subsys_interface_unregister(struct subsys_interface *sif);
-int subsys_system_register(struct bus_type *subsys,
+int subsys_system_register(const struct bus_type *subsys,
const struct attribute_group **groups);
-int subsys_virtual_register(struct bus_type *subsys,
+int subsys_virtual_register(const struct bus_type *subsys,
const struct attribute_group **groups);
/*
@@ -661,7 +661,6 @@ struct device_physical_location {
* @id: device instance
* @devres_lock: Spinlock to protect the resource of the device.
* @devres_head: The resources list of the device.
- * @knode_class: The node used to add the device to the class list.
* @class: The class of the device.
* @groups: Optional attribute groups.
* @release: Callback to free the device after all references have
@@ -1072,7 +1071,6 @@ int device_rename(struct device *dev, const char *new_name);
int device_move(struct device *dev, struct device *new_parent,
enum dpm_order dpm_order);
int device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid);
-int device_is_dependent(struct device *dev, void *target);
static inline bool device_supports_offline(struct device *dev)
{
diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h
index e25aab08f873d1..5ef4ec1c36c3b9 100644
--- a/include/linux/device/bus.h
+++ b/include/linux/device/bus.h
@@ -227,7 +227,7 @@ bus_find_device_by_acpi_dev(const struct bus_type *bus, const void *adev)
int bus_for_each_drv(const struct bus_type *bus, struct device_driver *start,
void *data, int (*fn)(struct device_driver *, void *));
-void bus_sort_breadthfirst(struct bus_type *bus,
+void bus_sort_breadthfirst(const struct bus_type *bus,
int (*compare)(const struct device *a,
const struct device *b));
/*
diff --git a/include/linux/device/class.h b/include/linux/device/class.h
index abf3d3bfb6fe4d..c576b49c55c22e 100644
--- a/include/linux/device/class.h
+++ b/include/linux/device/class.h
@@ -40,8 +40,6 @@ struct fwnode_handle;
* for the devices belonging to the class. Usually tied to
* device's namespace.
* @pm: The default device power management operations of this class.
- * @p: The private data of the driver core, no one other than the
- * driver core can touch this.
*
* A class is a higher-level view of a device that abstracts out low-level
* implementation details. Drivers may see a SCSI disk or an ATA disk, but,
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 1174beb94ab6da..b4ee8961e6236c 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -30,7 +30,7 @@ struct device;
extern int edac_op_state;
-struct bus_type *edac_get_sysfs_subsys(void);
+const struct bus_type *edac_get_sysfs_subsys(void);
static inline void opstate_init(void)
{
@@ -495,7 +495,7 @@ struct edac_raw_error_desc {
*/
struct mem_ctl_info {
struct device dev;
- struct bus_type *bus;
+ const struct bus_type *bus;
struct list_head link; /* for global list of mem_ctl_info structs */
diff --git a/include/linux/pm_clock.h b/include/linux/pm_clock.h
index ada3a0ab10bf22..68669ce187204a 100644
--- a/include/linux/pm_clock.h
+++ b/include/linux/pm_clock.h
@@ -91,10 +91,10 @@ static inline int devm_pm_clk_create(struct device *dev)
#endif
#ifdef CONFIG_HAVE_CLK
-extern void pm_clk_add_notifier(struct bus_type *bus,
+extern void pm_clk_add_notifier(const struct bus_type *bus,
struct pm_clk_notifier_block *clknb);
#else
-static inline void pm_clk_add_notifier(struct bus_type *bus,
+static inline void pm_clk_add_notifier(const struct bus_type *bus,
struct pm_clk_notifier_block *clknb)
{
}
diff --git a/include/linux/property.h b/include/linux/property.h
index 13174c3a0e19ca..60e35bd97398eb 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -80,6 +80,16 @@ int fwnode_property_match_string(const struct fwnode_handle *fwnode,
bool fwnode_device_is_available(const struct fwnode_handle *fwnode);
+static inline bool fwnode_device_is_big_endian(const struct fwnode_handle *fwnode)
+{
+ if (fwnode_property_present(fwnode, "big-endian"))
+ return true;
+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
+ fwnode_property_present(fwnode, "native-endian"))
+ return true;
+ return false;
+}
+
static inline
bool fwnode_device_is_compatible(const struct fwnode_handle *fwnode, const char *compat)
{
@@ -87,6 +97,22 @@ bool fwnode_device_is_compatible(const struct fwnode_handle *fwnode, const char
}
/**
+ * device_is_big_endian - check if a device has BE registers
+ * @dev: Pointer to the struct device
+ *
+ * Returns: true if the device has a "big-endian" property, or if the kernel
+ * was compiled for BE *and* the device has a "native-endian" property.
+ * Returns false otherwise.
+ *
+ * Callers would nominally use ioread32be/iowrite32be if
+ * device_is_big_endian() == true, or readl/writel otherwise.
+ */
+static inline bool device_is_big_endian(const struct device *dev)
+{
+ return fwnode_device_is_big_endian(dev_fwnode(dev));
+}
+
+/**
* device_is_compatible - match 'compatible' property of the device with a given string
* @dev: Pointer to the struct device
* @compat: The string to match 'compatible' property with
diff --git a/init/initramfs.c b/init/initramfs.c
index 8d0fd946cdd2b3..76deb48c38cb16 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -574,6 +574,16 @@ extern unsigned long __initramfs_size;
#include <linux/initrd.h>
#include <linux/kexec.h>
+static ssize_t raw_read(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t pos, size_t count)
+{
+ memcpy(buf, attr->private + pos, count);
+ return count;
+}
+
+static BIN_ATTR(initrd, 0440, raw_read, NULL, 0);
+
void __init reserve_initrd_mem(void)
{
phys_addr_t start;
@@ -715,8 +725,14 @@ done:
* If the initrd region is overlapped with crashkernel reserved region,
* free only memory that is not part of crashkernel region.
*/
- if (!do_retain_initrd && initrd_start && !kexec_free_initrd())
+ if (!do_retain_initrd && initrd_start && !kexec_free_initrd()) {
free_initrd_mem(initrd_start, initrd_end);
+ } else if (do_retain_initrd && initrd_start) {
+ bin_attr_initrd.size = initrd_end - initrd_start;
+ bin_attr_initrd.private = (void *)initrd_start;
+ if (sysfs_create_bin_file(firmware_kobj, &bin_attr_initrd))
+ pr_err("Failed to create initrd sysfs file");
+ }
initrd_start = 0;
initrd_end = 0;
diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
index 04d11a7dd95f9b..520a11cb12f44c 100644
--- a/kernel/cgroup/cgroup-v1.c
+++ b/kernel/cgroup/cgroup-v1.c
@@ -802,7 +802,7 @@ void cgroup1_release_agent(struct work_struct *work)
goto out_free;
ret = cgroup_path_ns(cgrp, pathbuf, PATH_MAX, &init_cgroup_ns);
- if (ret < 0 || ret >= PATH_MAX)
+ if (ret < 0)
goto out_free;
argv[0] = agentbuf;
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 8f3cef1a4d8a74..a66c088c851cfb 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1906,7 +1906,7 @@ int cgroup_show_path(struct seq_file *sf, struct kernfs_node *kf_node,
len = kernfs_path_from_node(kf_node, ns_cgroup->kn, buf, PATH_MAX);
spin_unlock_irq(&css_set_lock);
- if (len >= PATH_MAX)
+ if (len == -E2BIG)
len = -ERANGE;
else if (len > 0) {
seq_escape(sf, buf, " \t\n\\");
@@ -4182,20 +4182,6 @@ static struct kernfs_ops cgroup_kf_ops = {
.seq_show = cgroup_seqfile_show,
};
-/* set uid and gid of cgroup dirs and files to that of the creator */
-static int cgroup_kn_set_ugid(struct kernfs_node *kn)
-{
- struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID,
- .ia_uid = current_fsuid(),
- .ia_gid = current_fsgid(), };
-
- if (uid_eq(iattr.ia_uid, GLOBAL_ROOT_UID) &&
- gid_eq(iattr.ia_gid, GLOBAL_ROOT_GID))
- return 0;
-
- return kernfs_setattr(kn, &iattr);
-}
-
static void cgroup_file_notify_timer(struct timer_list *timer)
{
cgroup_file_notify(container_of(timer, struct cgroup_file,
@@ -4208,25 +4194,18 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp,
char name[CGROUP_FILE_NAME_MAX];
struct kernfs_node *kn;
struct lock_class_key *key = NULL;
- int ret;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
key = &cft->lockdep_key;
#endif
kn = __kernfs_create_file(cgrp->kn, cgroup_file_name(cgrp, cft, name),
cgroup_file_mode(cft),
- GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
+ current_fsuid(), current_fsgid(),
0, cft->kf_ops, cft,
NULL, key);
if (IS_ERR(kn))
return PTR_ERR(kn);
- ret = cgroup_kn_set_ugid(kn);
- if (ret) {
- kernfs_remove(kn);
- return ret;
- }
-
if (cft->file_offset) {
struct cgroup_file *cfile = (void *)css + cft->file_offset;
@@ -5629,7 +5608,9 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name,
goto out_cancel_ref;
/* create the directory */
- kn = kernfs_create_dir(parent->kn, name, mode, cgrp);
+ kn = kernfs_create_dir_ns(parent->kn, name, mode,
+ current_fsuid(), current_fsgid(),
+ cgrp, NULL);
if (IS_ERR(kn)) {
ret = PTR_ERR(kn);
goto out_stat_exit;
@@ -5774,10 +5755,6 @@ int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, umode_t mode)
*/
kernfs_get(cgrp->kn);
- ret = cgroup_kn_set_ugid(cgrp->kn);
- if (ret)
- goto out_destroy;
-
ret = css_populate_dir(&cgrp->self);
if (ret)
goto out_destroy;
@@ -6316,7 +6293,7 @@ int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns,
if (cgroup_on_dfl(cgrp) || !(tsk->flags & PF_EXITING)) {
retval = cgroup_path_ns_locked(cgrp, buf, PATH_MAX,
current->nsproxy->cgroup_ns);
- if (retval >= PATH_MAX)
+ if (retval == -E2BIG)
retval = -ENAMETOOLONG;
if (retval < 0)
goto out_unlock;
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 615daaf87f1fc8..fb29158ae825f4 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -4941,7 +4941,7 @@ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns,
retval = cgroup_path_ns(css->cgroup, buf, PATH_MAX,
current->nsproxy->cgroup_ns);
css_put(css);
- if (retval >= PATH_MAX)
+ if (retval == -E2BIG)
retval = -ENAMETOOLONG;
if (retval < 0)
goto out_free;