diff options
182 files changed, 1532 insertions, 1186 deletions
diff --git a/Documentation/ABI/testing/sysfs-kernel-address_bits b/Documentation/ABI/testing/sysfs-kernel-address_bits new file mode 100644 index 000000000000..5d09ff84d4d6 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-address_bits @@ -0,0 +1,10 @@ +What: /sys/kernel/address_bit +Date: May 2023 +KernelVersion: 6.3 +Contact: Thomas Weißschuh <linux@weissschuh.net> +Description: + The address size of the running kernel in bits. + + Access: Read + +Users: util-linux diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst index b6b4481e2474..df978127f2d7 100644 --- a/Documentation/process/embargoed-hardware-issues.rst +++ b/Documentation/process/embargoed-hardware-issues.rst @@ -251,6 +251,7 @@ an involved disclosed party. The current ambassadors list: IBM Z Christian Borntraeger <borntraeger@de.ibm.com> Intel Tony Luck <tony.luck@intel.com> Qualcomm Trilok Soni <tsoni@codeaurora.org> + Samsung Javier González <javier.gonz@samsung.com> Microsoft James Morris <jamorris@linux.microsoft.com> VMware diff --git a/arch/alpha/include/asm/dma-mapping.h b/arch/alpha/include/asm/dma-mapping.h index 0ee6a5c99b16..6ce7e2041685 100644 --- a/arch/alpha/include/asm/dma-mapping.h +++ b/arch/alpha/include/asm/dma-mapping.h @@ -4,7 +4,7 @@ extern const struct dma_map_ops alpha_pci_ops; -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) +static inline const struct dma_map_ops *get_arch_dma_ops(void) { #ifdef CONFIG_ALPHA_JENSEN return NULL; diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c index 97c42be71338..3ba70985e3a2 100644 --- a/arch/arm64/kernel/cacheinfo.c +++ b/arch/arm64/kernel/cacheinfo.c @@ -46,7 +46,7 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, int init_cache_level(unsigned int cpu) { unsigned int ctype, level, leaves; - int fw_level; + int fw_level, ret; struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) { @@ -59,13 +59,13 @@ int init_cache_level(unsigned int cpu) leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1; } - if (acpi_disabled) + if (acpi_disabled) { fw_level = of_find_last_cache_level(cpu); - else - fw_level = acpi_find_last_cache_level(cpu); - - if (fw_level < 0) - return fw_level; + } else { + ret = acpi_get_cache_info(cpu, &fw_level, NULL); + if (ret < 0) + fw_level = 0; + } if (level < fw_level) { /* diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h index a5d9d788eede..af6fa8e1597c 100644 --- a/arch/ia64/include/asm/dma-mapping.h +++ b/arch/ia64/include/asm/dma-mapping.h @@ -8,7 +8,7 @@ */ extern const struct dma_map_ops *dma_ops; -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) +static inline const struct dma_map_ops *get_arch_dma_ops(void) { return dma_ops; } diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h index 34de7b17b41b..0fee561ac796 100644 --- a/arch/mips/include/asm/dma-mapping.h +++ b/arch/mips/include/asm/dma-mapping.h @@ -6,7 +6,7 @@ extern const struct dma_map_ops jazz_dma_ops; -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) +static inline const struct dma_map_ops *get_arch_dma_ops(void) { #if defined(CONFIG_MACH_JAZZ) return &jazz_dma_ops; diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c index 8686e8c1c4e5..81c9f0a8880b 100644 --- a/arch/mips/sgi-ip22/ip22-gio.c +++ b/arch/mips/sgi-ip22/ip22-gio.c @@ -199,9 +199,9 @@ static struct attribute *gio_dev_attrs[] = { }; ATTRIBUTE_GROUPS(gio_dev); -static int gio_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int gio_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct gio_device *gio_dev = to_gio_device(dev); + const struct gio_device *gio_dev = to_gio_device(dev); add_uevent_var(env, "MODALIAS=gio:%x", gio_dev->id.id); return 0; diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h index d5bd94247371..635665004fe6 100644 --- a/arch/parisc/include/asm/dma-mapping.h +++ b/arch/parisc/include/asm/dma-mapping.h @@ -21,7 +21,7 @@ extern const struct dma_map_ops *hppa_dma_ops; -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) +static inline const struct dma_map_ops *get_arch_dma_ops(void) { return hppa_dma_ops; } diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index e7ee0c0c91d3..28f47285d448 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -552,7 +552,7 @@ static int parisc_generic_match(struct device *dev, struct device_driver *drv) return match_device(to_parisc_driver(drv), to_parisc_device(dev)); } -static ssize_t make_modalias(struct device *dev, char *buf) +static ssize_t make_modalias(const struct device *dev, char *buf) { const struct parisc_device *padev = to_parisc_device(dev); const struct parisc_device_id *id = &padev->id; @@ -562,7 +562,7 @@ static ssize_t make_modalias(struct device *dev, char *buf) (u32)id->sversion); } -static int parisc_uevent(struct device *dev, struct kobj_uevent_env *env) +static int parisc_uevent(const struct device *dev, struct kobj_uevent_env *env) { const struct parisc_device *padev; char modalias[40]; diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h index d503dbd7856c..a5f36546a052 100644 --- a/arch/powerpc/include/asm/ps3.h +++ b/arch/powerpc/include/asm/ps3.h @@ -396,7 +396,7 @@ static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv( return container_of(_drv, struct ps3_system_bus_driver, core); } static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev( - struct device *_dev) + const struct device *_dev) { return container_of(_dev, struct ps3_system_bus_device, core); } diff --git a/arch/powerpc/include/asm/vio.h b/arch/powerpc/include/asm/vio.h index e7479a4abf96..cc9b787627ad 100644 --- a/arch/powerpc/include/asm/vio.h +++ b/arch/powerpc/include/asm/vio.h @@ -161,10 +161,7 @@ static inline struct vio_driver *to_vio_driver(struct device_driver *drv) return container_of(drv, struct vio_driver, driver); } -static inline struct vio_dev *to_vio_dev(struct device *dev) -{ - return container_of(dev, struct vio_dev, dev); -} +#define to_vio_dev(__dev) container_of_const(__dev, struct vio_dev, dev) #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_VIO_H */ diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 38a7e02295c8..d6b5f5ecd515 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -439,7 +439,7 @@ static void ps3_system_bus_shutdown(struct device *_dev) dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); } -static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env) +static int ps3_system_bus_uevent(const struct device *_dev, struct kobj_uevent_env *env) { struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c index a870cada7acd..bb9c18682783 100644 --- a/arch/powerpc/platforms/pseries/ibmebus.c +++ b/arch/powerpc/platforms/pseries/ibmebus.c @@ -426,9 +426,14 @@ static struct attribute *ibmebus_bus_device_attrs[] = { }; ATTRIBUTE_GROUPS(ibmebus_bus_device); +static int ibmebus_bus_modalias(const struct device *dev, struct kobj_uevent_env *env) +{ + return of_device_uevent_modalias(dev, env); +} + struct bus_type ibmebus_bus_type = { .name = "ibmebus", - .uevent = of_device_uevent_modalias, + .uevent = ibmebus_bus_modalias, .bus_groups = ibmbus_bus_groups, .match = ibmebus_bus_bus_match, .probe = ibmebus_bus_device_probe, diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index 00ecac2c205b..770df9351aaa 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -1609,10 +1609,10 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv) return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); } -static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env) +static int vio_hotplug(const struct device *dev, struct kobj_uevent_env *env) { const struct vio_dev *vio_dev = to_vio_dev(dev); - struct device_node *dn; + const struct device_node *dn; const char *cp; dn = dev->of_node; diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index 90deabfe63ea..3a13113f1b29 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -113,48 +113,6 @@ static void fill_cacheinfo(struct cacheinfo **this_leaf, } } -int init_cache_level(unsigned int cpu) -{ - struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); - struct device_node *np = of_cpu_device_node_get(cpu); - struct device_node *prev = NULL; - int levels = 0, leaves = 0, level; - - if (of_property_read_bool(np, "cache-size")) - ++leaves; - if (of_property_read_bool(np, "i-cache-size")) - ++leaves; - if (of_property_read_bool(np, "d-cache-size")) - ++leaves; - if (leaves > 0) - levels = 1; - - prev = np; - while ((np = of_find_next_cache_node(np))) { - of_node_put(prev); - prev = np; - if (!of_device_is_compatible(np, "cache")) - break; - if (of_property_read_u32(np, "cache-level", &level)) - break; - if (level <= levels) - break; - if (of_property_read_bool(np, "cache-size")) - ++leaves; - if (of_property_read_bool(np, "i-cache-size")) - ++leaves; - if (of_property_read_bool(np, "d-cache-size")) - ++leaves; - levels = level; - } - - of_node_put(np); - this_cpu_ci->num_levels = levels; - this_cpu_ci->num_leaves = leaves; - - return 0; -} - int populate_cache_leaves(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h index 2f051343612e..55c12fc2ba63 100644 --- a/arch/sparc/include/asm/dma-mapping.h +++ b/arch/sparc/include/asm/dma-mapping.h @@ -4,7 +4,7 @@ extern const struct dma_map_ops *dma_ops; -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) +static inline const struct dma_map_ops *get_arch_dma_ops(void) { /* sparc32 uses per-device dma_ops */ return IS_ENABLED(CONFIG_SPARC64) ? dma_ops : NULL; diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h index 2d7bdf665fd3..8a0c3c11c9ce 100644 --- a/arch/sparc/include/asm/vio.h +++ b/arch/sparc/include/asm/vio.h @@ -488,10 +488,7 @@ static inline struct vio_driver *to_vio_driver(struct device_driver *drv) return container_of(drv, struct vio_driver, driver); } -static inline struct vio_dev *to_vio_dev(struct device *dev) -{ - return container_of(dev, struct vio_dev, dev); -} +#define to_vio_dev(__dev) container_of_const(__dev, struct vio_dev, dev) int vio_ldc_send(struct vio_driver_state *vio, void *data, int len); void vio_link_state_change(struct vio_driver_state *vio, int event); diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index 01122a208f94..b78df3a15a72 100644 --- a/arch/sparc/kernel/vio.c +++ b/arch/sparc/kernel/vio.c @@ -46,7 +46,7 @@ static const struct vio_device_id *vio_match_device( return NULL; } -static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env) +static int vio_hotplug(const struct device *dev, struct kobj_uevent_env *env) { const struct vio_dev *vio_dev = to_vio_dev(dev); diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 1c66708e3062..d1dac96ee30b 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -4,7 +4,7 @@ extern const struct dma_map_ops *dma_ops; -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) +static inline const struct dma_map_ops *get_arch_dma_ops(void) { return dma_ops; } diff --git a/block/genhd.c b/block/genhd.c index 093ef292e98f..d09d775c222a 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1200,7 +1200,7 @@ struct class block_class = { .dev_uevent = block_uevent, }; -static char *block_devnode(struct device *dev, umode_t *mode, +static char *block_devnode(const struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid) { struct gendisk *disk = dev_to_disk(dev); diff --git a/block/partitions/core.c b/block/partitions/core.c index b8112f52d388..7b8ef6296abd 100644 --- a/block/partitions/core.c +++ b/block/partitions/core.c @@ -254,9 +254,9 @@ static void part_release(struct device *dev) iput(dev_to_bdev(dev)->bd_inode); } -static int part_uevent(struct device *dev, struct kobj_uevent_env *env) +static int part_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct block_device *part = dev_to_bdev(dev); + const struct block_device *part = dev_to_bdev(dev); add_uevent_var(env, "PARTN=%u", part->bd_partno); if (part->bd_meta_info && part->bd_meta_info->volname[0]) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 0c05ccde1f7a..9531dd0fef50 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1014,7 +1014,7 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } -static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int acpi_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { return __acpi_device_uevent_modalias(to_acpi_device(dev), env); } diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index c3aa15571f16..0fbfbaa8d8e3 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -133,7 +133,7 @@ static void acpi_hide_nondev_subnodes(struct acpi_device_data *data) * -EINVAL: output error * -ENOMEM: output is truncated */ -static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias, +static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalias, int size) { int len; @@ -191,7 +191,7 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias, * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of * ACPI/PNP IDs. */ -static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias, +static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias, int size) { struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; @@ -239,7 +239,7 @@ static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias, return len; } -int __acpi_device_uevent_modalias(struct acpi_device *adev, +int __acpi_device_uevent_modalias(const struct acpi_device *adev, struct kobj_uevent_env *env) { int len; @@ -277,7 +277,7 @@ int __acpi_device_uevent_modalias(struct acpi_device *adev, * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001". */ -int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) +int acpi_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *env) { return __acpi_device_uevent_modalias(acpi_companion_match(dev), env); } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ec584442fb29..06ad497067ac 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -120,7 +120,7 @@ int acpi_bus_register_early_device(int type); Device Matching and Notification -------------------------------------------------------------------------- */ struct acpi_device *acpi_companion_match(const struct device *dev); -int __acpi_device_uevent_modalias(struct acpi_device *adev, +int __acpi_device_uevent_modalias(const struct acpi_device *adev, struct kobj_uevent_env *env); /* -------------------------------------------------------------------------- diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index c91342dcbcd6..10975bb603fb 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -81,6 +81,7 @@ static inline bool acpi_pptt_match_type(int table_type, int type) * acpi_pptt_walk_cache() - Attempt to find the requested acpi_pptt_cache * @table_hdr: Pointer to the head of the PPTT table * @local_level: passed res reflects this cache level + * @split_levels: Number of split cache levels (data/instruction). * @res: cache resource in the PPTT we want to walk * @found: returns a pointer to the requested level if found * @level: the requested cache level @@ -100,6 +101,7 @@ static inline bool acpi_pptt_match_type(int table_type, int type) */ static unsigned int acpi_pptt_walk_cache(struct acpi_table_header *table_hdr, unsigned int local_level, + unsigned int *split_levels, struct acpi_subtable_header *res, struct acpi_pptt_cache **found, unsigned int level, int type) @@ -113,8 +115,17 @@ static unsigned int acpi_pptt_walk_cache(struct acpi_table_header *table_hdr, while (cache) { local_level++; + if (!(cache->flags & ACPI_PPTT_CACHE_TYPE_VALID)) { + cache = fetch_pptt_cache(table_hdr, cache->next_level_of_cache); + continue; + } + + if (split_levels && + (acpi_pptt_match_type(cache->attributes, ACPI_PPTT_CACHE_TYPE_DATA) || + acpi_pptt_match_type(cache->attributes, ACPI_PPTT_CACHE_TYPE_INSTR))) + *split_levels = local_level; + if (local_level == level && - cache->flags & ACPI_PPTT_CACHE_TYPE_VALID && acpi_pptt_match_type(cache->attributes, type)) { if (*found != NULL && cache != *found) pr_warn("Found duplicate cache level/type unable to determine uniqueness\n"); @@ -135,8 +146,8 @@ static unsigned int acpi_pptt_walk_cache(struct acpi_table_header *table_hdr, static struct acpi_pptt_cache * acpi_find_cache_level(struct acpi_table_header *table_hdr, struct acpi_pptt_processor *cpu_node, - unsigned int *starting_level, unsigned int level, - int type) + unsigned int *starting_level, unsigned int *split_levels, + unsigned int level, int type) { struct acpi_subtable_header *res; unsigned int number_of_levels = *starting_level; @@ -149,7 +160,8 @@ acpi_find_cache_level(struct acpi_table_header *table_hdr, resource++; local_level = acpi_pptt_walk_cache(table_hdr, *starting_level, - res, &ret, level, type); + split_levels, res, &ret, + level, type); /* * we are looking for the max depth. Since its potentially * possible for a given node to have resources with differing @@ -165,29 +177,29 @@ acpi_find_cache_level(struct acpi_table_header *table_hdr, } /** - * acpi_count_levels() - Given a PPTT table, and a CPU node, count the caches + * acpi_count_levels() - Given a PPTT table, and a CPU node, count the cache + * levels and split cache levels (data/instruction). * @table_hdr: Pointer to the head of the PPTT table * @cpu_node: processor node we wish to count caches for + * @levels: Number of levels if success. + * @split_levels: Number of split cache levels (data/instruction) if + * success. Can by NULL. * * Given a processor node containing a processing unit, walk into it and count * how many levels exist solely for it, and then walk up each level until we hit * the root node (ignore the package level because it may be possible to have - * caches that exist across packages). Count the number of cache levels that - * exist at each level on the way up. - * - * Return: Total number of levels found. + * caches that exist across packages). Count the number of cache levels and + * split cache levels (data/instruction) that exist at each level on the way + * up. */ -static int acpi_count_levels(struct acpi_table_header *table_hdr, - struct acpi_pptt_processor *cpu_node) +static void acpi_count_levels(struct acpi_table_header *table_hdr, + struct acpi_pptt_processor *cpu_node, + unsigned int *levels, unsigned int *split_levels) { - int total_levels = 0; - do { - acpi_find_cache_level(table_hdr, cpu_node, &total_levels, 0, 0); + acpi_find_cache_level(table_hdr, cpu_node, levels, split_levels, 0, 0); cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent); } while (cpu_node); - - return total_levels; } /** @@ -281,19 +293,6 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he return NULL; } -static int acpi_find_cache_levels(struct acpi_table_header *table_hdr, - u32 acpi_cpu_id) -{ - int number_of_levels = 0; - struct acpi_pptt_processor *cpu; - - cpu = acpi_find_processor_node(table_hdr, acpi_cpu_id); - if (cpu) - number_of_levels = acpi_count_levels(table_hdr, cpu); - - return number_of_levels; -} - static u8 acpi_cache_type(enum cache_type type) { switch (type) { @@ -334,7 +333,7 @@ static struct acpi_pptt_cache *acpi_find_cache_node(struct acpi_table_header *ta while (cpu_node && !found) { found = acpi_find_cache_level(table_hdr, cpu_node, - &total_levels, level, acpi_type); + &total_levels, NULL, level, acpi_type); *node = cpu_node; cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent); } @@ -602,32 +601,48 @@ static int check_acpi_cpu_flag(unsigned int cpu, int rev, u32 flag) } /** - * acpi_find_last_cache_level() - Determines the number of cache levels for a PE + * acpi_get_cache_info() - Determine the number of cache levels and + * split cache levels (data/instruction) and for a PE. * @cpu: Kernel logical CPU number + * @levels: Number of levels if success. + * @split_levels: Number of levels being split (i.e. data/instruction) + * if success. Can by NULL. * * Given a logical CPU number, returns the number of levels of cache represented * in the PPTT. Errors caused by lack of a PPTT table, or otherwise, return 0 * indicating we didn't find any cache levels. * - * Return: Cache levels visible to this core. + * Return: -ENOENT if no PPTT table or no PPTT processor struct found. + * 0 on success. */ -int acpi_find_last_cache_level(unsigned int cpu) +int acpi_get_cache_info(unsigned int cpu, unsigned int *levels, + unsigned int *split_levels) { - u32 acpi_cpu_id; + struct acpi_pptt_processor *cpu_node; struct acpi_table_header *table; - int number_of_levels = 0; + u32 acpi_cpu_id; + + *levels = 0; + if (split_levels) + *split_levels = 0; table = acpi_get_pptt(); if (!table) return -ENOENT; - pr_debug("Cache Setup find last level CPU=%d\n", cpu); + pr_debug("Cache Setup: find cache levels for CPU=%d\n", cpu); acpi_cpu_id = get_acpi_id_for_cpu(cpu); - number_of_levels = acpi_find_cache_levels(table, acpi_cpu_id); - pr_debug("Cache Setup find last level level=%d\n", number_of_levels); + cpu_node = acpi_find_processor_node(table, acpi_cpu_id); + if (!cpu_node) + return -ENOENT; + + acpi_count_levels(table, cpu_node, levels, split_levels); - return number_of_levels; + pr_debug("Cache Setup: last_level=%d split_levels=%d\n", + *levels, split_levels ? *split_levels : -1); + + return 0; } /** diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index ff7454a38058..ce88af9eb562 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -235,9 +235,9 @@ static int amba_match(struct device *dev, struct device_driver *drv) return amba_lookup(pcdrv->id_table, pcdev) != NULL; } -static int amba_uevent(struct device *dev, struct kobj_uevent_env *env) +static int amba_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct amba_device *pcdev = to_amba_device(dev); + const struct amba_device *pcdev = to_amba_device(dev); int retval = 0; retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid); diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index e7d6e6657ffa..b1c1dd38ab01 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -736,7 +736,7 @@ void update_siblings_masks(unsigned int cpuid) ret = detect_cache_attributes(cpuid); if (ret && ret != -ENOENT) - pr_info("Early cacheinfo failed, ret = %d\n", ret); + pr_info("Early cacheinfo allocation failed, ret = %d\n", ret); /* update core and thread sibling masks */ for_each_online_cpu(cpu) { @@ -825,7 +825,7 @@ __weak int __init parse_acpi_topology(void) #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) void __init init_cpu_topology(void) { - int ret; + int cpu, ret; reset_cpu_topology(); ret = parse_acpi_topology(); @@ -840,6 +840,14 @@ void __init init_cpu_topology(void) reset_cpu_topology(); return; } + + for_each_possible_cpu(cpu) { + ret = fetch_cache_info(cpu); + if (ret) { + pr_err("Early cacheinfo failed, ret = %d\n", ret); + break; + } + } } void store_cpu_topology(unsigned int cpuid) diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c index 8c5e65930617..4d4c2c8d26c4 100644 --- a/drivers/base/auxiliary.c +++ b/drivers/base/auxiliary.c @@ -185,7 +185,7 @@ static int auxiliary_match(struct device *dev, struct device_driver *drv) return !!auxiliary_match_id(auxdrv->id_table, auxdev); } -static int auxiliary_uevent(struct device *dev, struct kobj_uevent_env *env) +static int auxiliary_uevent(const struct device *dev, struct kobj_uevent_env *env) { const char *name, *p; diff --git a/drivers/base/base.h b/drivers/base/base.h index 7d4803c03d3e..726a12a244c0 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -52,8 +52,23 @@ struct subsys_private { struct kset glue_dirs; struct class *class; + + struct lock_class_key lock_key; }; -#define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj) +#define to_subsys_private(obj) container_of_const(obj, struct subsys_private, subsys.kobj) + +static inline struct subsys_private *subsys_get(struct subsys_private *sp) +{ + if (sp) + kset_get(&sp->subsys); + return sp; +} + +static inline void subsys_put(struct subsys_private *sp) +{ + if (sp) + kset_put(&sp->subsys); +} struct driver_private { struct kobject kobj; @@ -130,6 +145,8 @@ struct kobject *virtual_device_parent(struct device *dev); extern int bus_add_device(struct device *dev); extern void bus_probe_device(struct device *dev); extern void bus_remove_device(struct device *dev); +void bus_notify(struct device *dev, enum bus_notifier_event value); +bool bus_is_registered(const struct bus_type *bus); extern int bus_add_driver(struct device_driver *drv); extern void bus_remove_driver(struct device_driver *drv); @@ -158,6 +175,8 @@ extern void device_block_probing(void); extern void device_unblock_probing(void); extern void deferred_probe_extend_timeout(void); extern void driver_deferred_probe_trigger(void); +const char *device_get_devnode(const struct device *dev, umode_t *mode, + kuid_t *uid, kgid_t *gid, const char **tmp); /* /sys/devices directory */ extern struct kset *devices_kset; diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 4ec6dbab73be..cfe8615d5106 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -6,6 +6,7 @@ * Copyright (c) 2002-3 Open Source Development Labs * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (c) 2007 Novell Inc. + * Copyright (c) 2023 Greg Kroah-Hartman <gregkh@linuxfoundation.org> */ #include <linux/async.h> @@ -24,6 +25,9 @@ /* /sys/devices/system */ static struct kset *system_kset; +/* /sys/bus */ +static struct kset *bus_kset; + #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) /* @@ -39,19 +43,63 @@ static struct kset *system_kset; static int __must_check bus_rescan_devices_helper(struct device *dev, void *data); +/** + * bus_to_subsys - Turn a struct bus_type into a struct subsys_private + * + * @bus: pointer to the struct bus_type to look up + * + * The driver core internals needs to work on the subsys_private structure, not + * the external struct bus_type pointer. This function walks the list of + * registered busses in the system and finds the matching one and returns the + * internal struct subsys_private that relates to that bus. + * + * Note, the reference count of the return value is INCREMENTED if it is not + * NULL. A call to subsys_put() must be done when finished with the pointer in + * order for it to be properly freed. + */ +static struct subsys_private *bus_to_subsys(const struct bus_type *bus) +{ + struct subsys_private *sp = NULL; + struct kobject *kobj; + + if (!bus) + return NULL; + + spin_lock(&bus_kset->list_lock); + + if (list_empty(&bus_kset->list)) + goto done; + + list_for_each_entry(kobj, &bus_kset->list, entry) { + struct kset *kset = container_of(kobj, struct kset, kobj); + + sp = container_of_const(kset, struct subsys_private, subsys); + if (sp->bus == bus) + goto done; + } + sp = NULL; +done: + sp = subsys_get(sp); + spin_unlock(&bus_kset->list_lock); + return sp; +} + static struct bus_type *bus_get(struct bus_type *bus) { - if (bus) { - kset_get(&bus->p->subsys); + struct subsys_private *sp = bus_to_subsys(bus); + + if (sp) return bus; - } return NULL; } -static void bus_put(struct bus_type *bus) +static void bus_put(const struct bus_type *bus) { - if (bus) - kset_put(&bus->p->subsys); + struct subsys_private *sp = bus_to_subsys(bus); + + /* two puts are required as the call to bus_to_subsys incremented it again */ + subsys_put(sp); + subsys_put(sp); } static ssize_t drv_attr_show(struct kobject *kobj, struct attribute *attr, @@ -91,7 +139,7 @@ static void driver_release(struct kobject *kobj) kfree(drv_priv); } -static struct kobj_type driver_ktype = { +static const struct kobj_type driver_ktype = { .sysfs_ops = &driver_sysfs_ops, .release = driver_release, }; @@ -128,37 +176,42 @@ static const struct sysfs_ops bus_sysfs_ops = { .store = bus_attr_store, }; -int bus_create_file(struct bus_type *bus, struct bus_attribute *attr) +int bus_create_file(const struct bus_type *bus, struct bus_attribute *attr) { + struct subsys_private *sp = bus_to_subsys(bus); int error; - if (bus_get(bus)) { - error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr); - bus_put(bus); - } else - error = -EINVAL; + + if (!sp) + return -EINVAL; + + error = sysfs_create_file(&sp->subsys.kobj, &attr->attr); + + subsys_put(sp); return error; } EXPORT_SYMBOL_GPL(bus_create_file); -void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr) +void bus_remove_file(const struct bus_type *bus, struct bus_attribute *attr) { - if (bus_get(bus)) { - sysfs_remove_file(&bus->p->subsys.kobj, &attr->attr); - bus_put(bus); - } + struct subsys_private *sp = bus_to_subsys(bus); + + if (!sp) + return; + + sysfs_remove_file(&sp->subsys.kobj, &attr->attr); + subsys_put(sp); } EXPORT_SYMBOL_GPL(bus_remove_file); static void bus_release(struct kobject *kobj) { struct subsys_private *priv = to_subsys_private(kobj); - struct bus_type *bus = priv->bus; + lockdep_unregister_key(&priv->lock_key); kfree(priv); - bus->p = NULL; } -static struct kobj_type bus_ktype = { +static const struct kobj_type bus_ktype = { .sysfs_ops = &bus_sysfs_ops, .release = bus_release, }; @@ -176,8 +229,6 @@ static const struct kset_uevent_ops bus_uevent_ops = { .filter = bus_uevent_filter, }; -static struct kset *bus_kset; - /* Manually detach a device from its associated driver. */ static ssize_t unbind_store(struct device_driver *drv, const char *buf, size_t count) @@ -225,16 +276,31 @@ static DRIVER_ATTR_IGNORE_LOCKDEP(bind, 0200, NULL, bind_store); static ssize_t drivers_autoprobe_show(struct bus_type *bus, char *buf) { - return sysfs_emit(buf, "%d\n", bus->p->drivers_autoprobe); + struct subsys_private *sp = bus_to_subsys(bus); + int ret; + + if (!sp) + return -EINVAL; + + ret = sysfs_emit(buf, "%d\n", sp->drivers_autoprobe); + subsys_put(sp); + return ret; } static ssize_t drivers_autoprobe_store(struct bus_type *bus, const char *buf, size_t count) { + struct subsys_private *sp = bus_to_subsys(bus); + + if (!sp) + return -EINVAL; + if (buf[0] == '0') - bus->p->drivers_autoprobe = 0; + sp->drivers_autoprobe = 0; else - bus->p->drivers_autoprobe = 1; + sp->drivers_autoprobe = 1; + + subsys_put(sp); return count; } @@ -285,21 +351,23 @@ static struct device *next_device(struct klist_iter *i) * to retain this data, it should do so, and increment the reference * count in the supplied callback. */ -int bus_for_each_dev(struct bus_type *bus, struct device *start, +int bus_for_each_dev(const struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *, void *)) { + struct subsys_private *sp = bus_to_subsys(bus); struct klist_iter i; struct device *dev; int error = 0; - if (!bus || !bus->p) + if (!sp) return -EINVAL; - klist_iter_init_node(&bus->p->klist_devices, &i, + klist_iter_init_node(&sp->klist_devices, &i, (start ? &start->p->knode_bus : NULL)); while (!error && (dev = next_device(&i))) error = fn(dev, data); klist_iter_exit(&i); + subsys_put(sp); return error; } EXPORT_SYMBOL_GPL(bus_for_each_dev); @@ -319,67 +387,28 @@ EXPORT_SYMBOL_GPL(bus_for_each_dev); * if it does. If the callback returns non-zero, this function will * return to the caller and not iterate over any more devices. */ -struct device *bus_find_device(struct bus_type *bus, +struct device *bus_find_device(const struct bus_type *bus, struct device *start, const void *data, int (*match)(struct device *dev, const void *data)) { + struct subsys_private *sp = bus_to_subsys(bus); struct klist_iter i; struct device *dev; - if (!bus || !bus->p) + if (!sp) return NULL; - klist_iter_init_node(&bus->p->klist_devices, &i, + klist_iter_init_node(&sp->klist_devices, &i, (start ? &start->p->knode_bus : NULL)); while ((dev = next_device(&i))) if (match(dev, data) && get_device(dev)) break; klist_iter_exit(&i); + subsys_put(sp); return dev; } EXPORT_SYMBOL_GPL(bus_find_device); -/** - * subsys_find_device_by_id - find a device with a specific enumeration number - * @subsys: subsystem - * @id: index 'id' in struct device - * @hint: device to check first - * - * Check the hint's next object and if it is a match return it directly, - * otherwise, fall back to a full list search. Either way a reference for - * the returned object is taken. - */ -struct device *subsys_find_device_by_id(struct bus_type *subsys, unsigned int id, - struct device *hint) -{ - struct klist_iter i; - struct device *dev; - - if (!subsys) - return NULL; - - if (hint) { - klist_iter_init_node(&subsys->p->klist_devices, &i, &hint->p->knode_bus); - dev = next_device(&i); - if (dev && dev->id == id && get_device(dev)) { - klist_iter_exit(&i); - return dev; - } - klist_iter_exit(&i); - } - - klist_iter_init_node(&subsys->p->klist_devices, &i, NULL); - while ((dev = next_device(&i))) { - if (dev->id == id && get_device(dev)) { - klist_iter_exit(&i); - return dev; - } - } - klist_iter_exit(&i); - return NULL; -} -EXPORT_SYMBOL_GPL(subsys_find_device_by_id); - static struct device_driver *next_driver(struct klist_iter *i) { struct klist_node *n = klist_next(i); @@ -411,21 +440,23 @@ static struct device_driver *next_driver(struct klist_iter *i) * in the callback. It must also be sure to increment the refcount * so it doesn't disappear before returning to the caller. */ -int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, +int bus_for_each_drv(const struct bus_type *bus, struct device_driver *start, void *data, int (*fn)(struct device_driver *, void *)) { + struct subsys_private *sp = bus_to_subsys(bus); struct klist_iter i; struct device_driver *drv; int error = 0; - if (!bus) + if (!sp) return -EINVAL; - klist_iter_init_node(&bus->p->klist_drivers, &i, + klist_iter_init_node(&sp->klist_drivers, &i, start ? &start->p->knode_bus : NULL); while ((drv = next_driver(&i)) && !error) error = fn(drv, data); klist_iter_exit(&i); + subsys_put(sp); return error; } EXPORT_SYMBOL_GPL(bus_for_each_drv); @@ -440,32 +471,46 @@ EXPORT_SYMBOL_GPL(bus_for_each_drv); */ int bus_add_device(struct device *dev) { - struct bus_type *bus = bus_get(dev->bus); - int error = 0; + struct subsys_private *sp = bus_to_subsys(dev->bus); + int error; - if (bus) { - pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev)); - error = device_add_groups(dev, bus->dev_groups); - if (error) - goto out_put; - error = sysfs_create_link(&bus->p->devices_kset->kobj, - &dev->kobj, dev_name(dev)); - if (error) - goto out_groups; - error = sysfs_create_link(&dev->kobj, - &dev->bus->p->subsys.kobj, "subsystem"); - if (error) - goto out_subsys; - klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices); + if (!sp) { + /* + * This is a normal operation for many devices that do not + * have a bus assigned to them, just say that all went + * well. + */ + return 0; } + + /* + * Reference in sp is now incremented and will be dropped when + * the device is removed from the bus + */ + + pr_debug("bus: '%s': add device %s\n", sp->bus->name, dev_name(dev)); + + error = device_add_groups(dev, sp->bus->dev_groups); + if (error) + goto out_put; + + error = sysfs_create_link(&sp->devices_kset->kobj, &dev->kobj, dev_name(dev)); + if (error) + goto out_groups; + + error = sysfs_create_link(&dev->kobj, &sp->subsys.kobj, "subsystem"); + if (error) + goto out_subsys; + + klist_add_tail(&dev->p->knode_bus, &sp->klist_devices); return 0; out_subsys: - sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev)); + sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev)); out_groups: - device_remove_groups(dev, bus->dev_groups); + device_remove_groups(dev, sp->bus->dev_groups); out_put: - bus_put(dev->bus); + subsys_put(sp); return error; } @@ -477,20 +522,21 @@ out_put: */ void bus_probe_device(struct device *dev) { - struct bus_type *bus = dev->bus; + struct subsys_private *sp = bus_to_subsys(dev->bus); struct subsys_interface *sif; - if (!bus) + if (!sp) return; - if (bus->p->drivers_autoprobe) + if (sp->drivers_autoprobe) device_initial_probe(dev); - mutex_lock(&bus->p->mutex); - list_for_each_entry(sif, &bus->p->interfaces, node) + mutex_lock(&sp->mutex); + list_for_each_entry(sif, &sp->interfaces, node) if (sif->add_dev) sif->add_dev(dev, sif); - mutex_unlock(&bus->p->mutex); + mutex_unlock(&sp->mutex); + subsys_put(sp); } /** @@ -505,21 +551,20 @@ void bus_probe_device(struct device *dev) */ void bus_remove_device(struct device *dev) { - struct bus_type *bus = dev->bus; + struct subsys_private *sp = bus_to_subsys(dev->bus); struct subsys_interface *sif; - if (!bus) + if (!sp) return; - mutex_lock(&bus->p->mutex); - list_for_each_entry(sif, &bus->p->interfaces, node) + mutex_lock(&sp->mutex); + list_for_each_entry(sif, &sp->interfaces, node) if (sif->remove_dev) sif->remove_dev(dev, sif); - mutex_unlock(&bus->p->mutex); + mutex_unlock(&sp->mutex); sysfs_remove_link(&dev->kobj, "subsystem"); - sysfs_remove_link(&dev->bus->p->devices_kset->kobj, - dev_name(dev)); + sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev)); device_remove_groups(dev, dev->bus->dev_groups); if (klist_node_attached(&dev->p->knode_bus)) klist_del(&dev->p->knode_bus); @@ -527,7 +572,14 @@ void bus_remove_device(struct device *dev) pr_debug("bus: '%s': remove device %s\n", dev->bus->name, dev_name(dev)); device_release_driver(dev); - bus_put(dev->bus); + + /* + * Decrement the reference count twice, once for the bus_to_subsys() + * call in the start of this function, and the second one from the + * reference increment in bus_add_device() + */ + subsys_put(sp); + subsys_put(sp); } static int __must_check add_bind_files(struct device_driver *drv) @@ -552,7 +604,7 @@ static void remove_bind_files(struct device_driver *drv) static BUS_ATTR_WO(drivers_probe); static BUS_ATTR_RW(drivers_autoprobe); -static int add_probe_files(struct bus_type *bus) +static int add_probe_files(const struct bus_type *bus) { int retval; @@ -567,7 +619,7 @@ out: return retval; } -static void remove_probe_files(struct bus_type *bus) +static void remove_probe_files(const struct bus_type *bus) { bus_remove_file(bus, &bus_attr_drivers_autoprobe); bus_remove_file(bus, &bus_attr_drivers_probe); @@ -589,15 +641,18 @@ static DRIVER_ATTR_WO(uevent); */ int bus_add_driver(struct device_driver *drv) { - struct bus_type *bus; + struct subsys_private *sp = bus_to_subsys(drv->bus); struct driver_private *priv; int error = 0; - bus = bus_get(drv->bus); - if (!bus) + if (!sp) return -EINVAL; - pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name); + /* + * Reference in sp is now incremented and will be dropped when + * the driver is removed from the bus + */ + pr_debug("bus: '%s': add driver %s\n", sp->bus->name, drv->name); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { @@ -607,14 +662,14 @@ int bus_add_driver(struct device_driver *drv) klist_init(&priv->klist_devices, NULL, NULL); priv->driver = drv; drv->p = priv; - priv->kobj.kset = bus->p->drivers_kset; + priv->kobj.kset = sp->drivers_kset; error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, "%s", drv->name); if (error) goto out_unregister; - klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); - if (drv->bus->p->drivers_autoprobe) { + klist_add_tail(&priv->knode_bus, &sp->klist_drivers); + if (sp->drivers_autoprobe) { error = driver_attach(drv); if (error) goto out_del_list; @@ -626,7 +681,7 @@ int bus_add_driver(struct device_driver *drv) printk(KERN_ERR "%s: uevent attr (%s) failed\n", __func__, drv->name); } - error = driver_add_groups(drv, bus->drv_groups); + error = driver_add_groups(drv, sp->bus->drv_groups); if (error) { /* How the hell do we get out of this pickle? Give up */ printk(KERN_ERR "%s: driver_add_groups(%s) failed\n", @@ -651,7 +706,7 @@ out_unregister: /* drv->p is freed in driver_release() */ drv->p = NULL; out_put_bus: - bus_put(bus); + subsys_put(sp); return error; } @@ -665,19 +720,29 @@ out_put_bus: */ void bus_remove_driver(struct device_driver *drv) { - if (!drv->bus) + struct subsys_private *sp = bus_to_subsys(drv->bus); + + if (!sp) return; + pr_debug("bus: '%s': remove driver %s\n", sp->bus->name, drv->name); + if (!drv->suppress_bind_attrs) remove_bind_files(drv); - driver_remove_groups(drv, drv->bus->drv_groups); + driver_remove_groups(drv, sp->bus->drv_groups); driver_remove_file(drv, &driver_attr_uevent); klist_remove(&drv->p->knode_bus); - pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name); driver_detach(drv); module_remove_driver(drv); kobject_put(&drv->p->kobj); - bus_put(drv->bus); + + /* + * Decrement the reference count twice, once for the bus_to_subsys() + * call in the start of this function, and the second one from the + * reference increment in bus_add_driver() + */ + subsys_put(sp); + subsys_put(sp); } /* Helper for bus_rescan_devices's iter */ @@ -727,18 +792,6 @@ int device_reprobe(struct device *dev) } EXPORT_SYMBOL_GPL(device_reprobe); -static int bus_add_groups(struct bus_type *bus, - const struct attribute_group **groups) -{ - return sysfs_create_groups(&bus->p->subsys.kobj, groups); -} - -static void bus_remove_groups(struct bus_type *bus, - const struct attribute_group **groups) -{ - sysfs_remove_groups(&bus->p->subsys.kobj, groups); -} - static void klist_devices_get(struct klist_node *n) { struct device_private *dev_prv = to_device_private_bus(n); @@ -758,10 +811,18 @@ static void klist_devices_put(struct klist_node *n) static ssize_t bus_uevent_store(struct bus_type *bus, const char *buf, size_t count) { - int rc; + struct subsys_private *sp = bus_to_subsys(bus); + int ret; - rc = kobject_synth_uevent(&bus->p->subsys.kobj, buf, count); - return rc ? rc : count; + if (!sp) + return -EINVAL; + + ret = kobject_synth_uevent(&sp->subsys.kobj, buf, count); + subsys_put(sp); + + if (ret) + return ret; + return count; } /* * "open code" the old BUS_ATTR() macro here. We want to use BUS_ATTR_WO() @@ -784,23 +845,24 @@ int bus_register(struct bus_type *bus) { int retval; struct subsys_private *priv; - struct lock_class_key *key = &bus->lock_key; + struct kobject *bus_kobj; + struct lock_class_key *key; priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL); if (!priv) return -ENOMEM; priv->bus = bus; - bus->p = priv; BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier); - retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); + bus_kobj = &priv->subsys.kobj; + retval = kobject_set_name(bus_kobj, "%s", bus->name); if (retval) goto out; - priv->subsys.kobj.kset = bus_kset; - priv->subsys.kobj.ktype = &bus_ktype; + bus_kobj->kset = bus_kset; + bus_kobj->ktype = &bus_ktype; priv->drivers_autoprobe = 1; retval = kset_register(&priv->subsys); @@ -811,21 +873,21 @@ int bus_register(struct bus_type *bus) if (retval) goto bus_uevent_fail; - priv->devices_kset = kset_create_and_add("devices", NULL, - &priv->subsys.kobj); + priv->devices_kset = kset_create_and_add("devices", NULL, bus_kobj); if (!priv->devices_kset) { retval = -ENOMEM; goto bus_devices_fail; } - priv->drivers_kset = kset_create_and_add("drivers", NULL, - &priv->subsys.kobj); + priv->drivers_kset = kset_create_and_add("drivers", NULL, bus_kobj); if (!priv->drivers_kset) { retval = -ENOMEM; goto bus_drivers_fail; } INIT_LIST_HEAD(&priv->interfaces); + key = &priv->lock_key; + lockdep_register_key(key); __mutex_init(&priv->mutex, "subsys mutex", key); klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); klist_init(&priv->klist_drivers, NULL, NULL); @@ -834,7 +896,7 @@ int bus_register(struct bus_type *bus) if (retval) goto bus_probe_files_fail; - retval = bus_add_groups(bus, bus->bus_groups); + retval = sysfs_create_groups(bus_kobj, bus->bus_groups); if (retval) goto bus_groups_fail; @@ -844,16 +906,15 @@ int bus_register(struct bus_type *bus) bus_groups_fail: remove_probe_files(bus); bus_probe_files_fail: - kset_unregister(bus->p->drivers_kset); + kset_unregister(priv->drivers_kset); bus_drivers_fail: - kset_unregister(bus->p->devices_kset); + kset_unregister(priv->devices_kset); bus_devices_fail: bus_remove_file(bus, &bus_attr_uevent); bus_uevent_fail: - kset_unregister(&bus->p->subsys); + kset_unregister(&priv->subsys); out: - kfree(bus->p); - bus->p = NULL; + kfree(priv); return retval; } EXPORT_SYMBOL_GPL(bus_register); @@ -865,43 +926,82 @@ EXPORT_SYMBOL_GPL(bus_register); * Unregister the child subsystems and the bus itself. * Finally, we call bus_put() to release the refcount */ -void bus_unregister(struct bus_type *bus) +void bus_unregister(const struct bus_type *bus) { + struct subsys_private *sp = bus_to_subsys(bus); + struct kobject *bus_kobj; + + if (!sp) + return; + pr_debug("bus: '%s': unregistering\n", bus->name); if (bus->dev_root) device_unregister(bus->dev_root); - bus_remove_groups(bus, bus->bus_groups); + + bus_kobj = &sp->subsys.kobj; + sysfs_remove_groups(bus_kobj, bus->bus_groups); remove_probe_files(bus); - kset_unregister(bus->p->drivers_kset); - kset_unregister(bus->p->devices_kset); bus_remove_file(bus, &bus_attr_uevent); - kset_unregister(&bus->p->subsys); + + kset_unregister(sp->drivers_kset); + kset_unregister(sp->devices_kset); + kset_unregister(&sp->subsys); + subsys_put(sp); } EXPORT_SYMBOL_GPL(bus_unregister); -int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb) +int bus_register_notifier(const struct bus_type *bus, struct notifier_block *nb) { - return blocking_notifier_chain_register(&bus->p->bus_notifier, nb); + struct subsys_private *sp = bus_to_subsys(bus); + int retval; + + if (!sp) + return -EINVAL; + + retval = blocking_notifier_chain_register(&sp->bus_notifier, nb); + subsys_put(sp); + return retval; } EXPORT_SYMBOL_GPL(bus_register_notifier); -int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb) +int bus_unregister_notifier(const struct bus_type *bus, struct notifier_block *nb) { - return blocking_notifier_chain_unregister(&bus->p->bus_notifier, nb); + struct subsys_private *sp = bus_to_subsys(bus); + int retval; + + if (!sp) + return -EINVAL; + retval = blocking_notifier_chain_unregister(&sp->bus_notifier, nb); + subsys_put(sp); + return retval; } EXPORT_SYMBOL_GPL(bus_unregister_notifier); -struct kset *bus_get_kset(struct bus_type *bus) +void bus_notify(struct device *dev, enum bus_notifier_event value) { - return &bus->p->subsys; + struct subsys_private *sp = bus_to_subsys(dev->bus); + + if (!sp) + return; + + blocking_notifier_call_chain(&sp->bus_notifier, value, dev); + subsys_put(sp); } -EXPORT_SYMBOL_GPL(bus_get_kset); -struct klist *bus_get_device_klist(struct bus_type *bus) +struct kset *bus_get_kset(const struct bus_type *bus) { - return &bus->p->klist_devices; + struct subsys_private *sp = bus_to_subsys(bus); + struct kset *kset; + + if (!sp) + return NULL; + + kset = &sp->subsys; + subsys_put(sp); + + return kset; } -EXPORT_SYMBOL_GPL(bus_get_device_klist); +EXPORT_SYMBOL_GPL(bus_get_kset); /* * Yes, this forcibly breaks the klist abstraction temporarily. It @@ -934,13 +1034,16 @@ void bus_sort_breadthfirst(struct bus_type *bus, int (*compare)(const struct device *a, const struct device *b)) { + struct subsys_private *sp = bus_to_subsys(bus); LIST_HEAD(sorted_devices); struct klist_node *n, *tmp; struct device_private *dev_prv; struct device *dev; struct klist *device_klist; - device_klist = bus_get_device_klist(bus); + if (!sp) + return; + device_klist = &sp->klist_devices; spin_lock(&device_klist->k_lock); list_for_each_entry_safe(n, tmp, &device_klist->k_list, n_node) { @@ -950,13 +1053,19 @@ void bus_sort_breadthfirst(struct bus_type *bus, } list_splice(&sorted_devices, &device_klist->k_list); spin_unlock(&device_klist->k_lock); + subsys_put(sp); } EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); +struct subsys_dev_iter { + struct klist_iter ki; + const struct device_type *type; +}; + /** * subsys_dev_iter_init - initialize subsys device iterator * @iter: subsys iterator to initialize - * @subsys: the subsys we wanna iterate over + * @sp: the subsys private (i.e. bus) we wanna iterate over * @start: the device to start iterating from, if any * @type: device_type of the devices to iterate over, NULL for all * @@ -965,17 +1074,16 @@ EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); * otherwise if it is NULL, the iteration starts at the beginning of * the list. */ -void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys, - struct device *start, const struct device_type *type) +static void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct subsys_private *sp, + struct device *start, const struct device_type *type) { struct klist_node *start_knode = NULL; if (start) start_knode = &start->p->knode_bus; - klist_iter_init_node(&subsys->p->klist_devices, &iter->ki, start_knode); + klist_iter_init_node(&sp->klist_devices, &iter->ki, start_knode); iter->type = type; } -EXPORT_SYMBOL_GPL(subsys_dev_iter_init); /** * subsys_dev_iter_next - iterate to the next device @@ -989,7 +1097,7 @@ EXPORT_SYMBOL_GPL(subsys_dev_iter_init); * free to do whatever it wants to do with the device including * calling back into subsys code. */ -struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter) +static struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter) { struct klist_node *knode; struct device *dev; @@ -1003,7 +1111,6 @@ struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter) return dev; } } -EXPORT_SYMBOL_GPL(subsys_dev_iter_next); /** * subsys_dev_iter_exit - finish iteration @@ -1012,34 +1119,38 @@ EXPORT_SYMBOL_GPL(subsys_dev_iter_next); * Finish an iteration. Always call this function after iteration is * complete whether the iteration ran till the end or not. */ -void subsys_dev_iter_exit(struct subsys_dev_iter *iter) +static void subsys_dev_iter_exit(struct subsys_dev_iter *iter) { klist_iter_exit(&iter->ki); } -EXPORT_SYMBOL_GPL(subsys_dev_iter_exit); int subsys_interface_register(struct subsys_interface *sif) { - struct bus_type *subsys; + struct subsys_private *sp; struct subsys_dev_iter iter; struct device *dev; if (!sif || !sif->subsys) return -ENODEV; - subsys = bus_get(sif->subsys); - if (!subsys) + sp = bus_to_subsys(sif->subsys); + if (!sp) return -EINVAL; - mutex_lock(&subsys->p->mutex); - list_add_tail(&sif->node, &subsys->p->interfaces); + /* + * Reference in sp is now incremented and will be dropped when + * the interface is removed from the bus + */ + + mutex_lock(&sp->mutex); + list_add_tail(&sif->node, &sp->interfaces); if (sif->add_dev) { - subsys_dev_iter_init(&iter, subsys, NULL, NULL); + subsys_dev_iter_init(&iter, sp, NULL, NULL); while ((dev = subsys_dev_iter_next(&iter))) sif->add_dev(dev, sif); subsys_dev_iter_exit(&iter); } - mutex_unlock(&subsys->p->mutex); + mutex_unlock(&sp->mutex); return 0; } @@ -1047,26 +1158,34 @@ EXPORT_SYMBOL_GPL(subsys_interface_register); void subsys_interface_unregister(struct subsys_interface *sif) { - struct bus_type *subsys; + struct subsys_private *sp; struct subsys_dev_iter iter; struct device *dev; if (!sif || !sif->subsys) return; - subsys = sif->subsys; + sp = bus_to_subsys(sif->subsys); + if (!sp) + return; - mutex_lock(&subsys->p->mutex); + mutex_lock(&sp->mutex); list_del_init(&sif->node); if (sif->remove_dev) { - subsys_dev_iter_init(&iter, subsys, NULL, NULL); + subsys_dev_iter_init(&iter, sp, NULL, NULL); while ((dev = subsys_dev_iter_next(&iter))) sif->remove_dev(dev, sif); subsys_dev_iter_exit(&iter); } - mutex_unlock(&subsys->p->mutex); - - bus_put(subsys); + mutex_unlock(&sp->mutex); + + /* + * Decrement the reference count twice, once for the bus_to_subsys() + * call in the start of this function, and the second one from the + * reference increment in subsys_interface_register() + */ + subsys_put(sp); + subsys_put(sp); } EXPORT_SYMBOL_GPL(subsys_interface_unregister); @@ -1166,6 +1285,76 @@ int subsys_virtual_register(struct bus_type *subsys, } EXPORT_SYMBOL_GPL(subsys_virtual_register); +/** + * driver_find - locate driver on a bus by its name. + * @name: name of the driver. + * @bus: bus to scan for the driver. + * + * Call kset_find_obj() to iterate over list of drivers on + * a bus to find driver by name. Return driver if found. + * + * This routine provides no locking to prevent the driver it returns + * from being unregistered or unloaded while the caller is using it. + * The caller is responsible for preventing this. + */ +struct device_driver *driver_find(const char *name, struct bus_type *bus) +{ + struct subsys_private *sp = bus_to_subsys(bus); + struct kobject *k; + struct driver_private *priv; + + if (!sp) + return NULL; + + k = kset_find_obj(sp->drivers_kset, name); + subsys_put(sp); + if (!k) + return NULL; + + priv = to_driver(k); + + /* Drop reference added by kset_find_obj() */ + kobject_put(k); + return priv->driver; +} +EXPORT_SYMBOL_GPL(driver_find); + +/* + * Warning, the value could go to "removed" instantly after calling this function, so be very + * careful when calling it... + */ +bool bus_is_registered(const struct bus_type *bus) +{ + struct subsys_private *sp = bus_to_subsys(bus); + bool is_initialized = false; + + if (sp) { + is_initialized = true; + subsys_put(sp); + } + return is_initialized; +} + +/** + * bus_get_dev_root - return a pointer to the "device root" of a bus + * @bus: bus to return the device root of. + * + * If a bus has a "device root" structure, return it, WITH THE REFERENCE + * COUNT INCREMENTED. + * + * Note, when finished with the device, a call to put_device() is required. + * + * If the device root is not present (or bus is not a valid pointer), NULL + * will be returned. + */ +struct device *bus_get_dev_root(const struct bus_type *bus) +{ + if (bus) + return get_device(bus->dev_root); + return NULL; +} +EXPORT_SYMBOL_GPL(bus_get_dev_root); + int __init buses_init(void) { bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 950b22cdb5f7..f6573c335f4c 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -229,8 +229,71 @@ static int cache_setup_of_node(unsigned int cpu) return 0; } + +static int of_count_cache_leaves(struct device_node *np) +{ + unsigned int leaves = 0; + + if (of_property_read_bool(np, "cache-size")) + ++leaves; + if (of_property_read_bool(np, "i-cache-size")) + ++leaves; + if (of_property_read_bool(np, "d-cache-size")) + ++leaves; + + if (!leaves) { + /* The '[i-|d-|]cache-size' property is required, but + * if absent, fallback on the 'cache-unified' property. + */ + if (of_property_read_bool(np, "cache-unified")) + return 1; + else + return 2; + } + + return leaves; +} + +int init_of_cache_level(unsigned int cpu) +{ + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); + struct device_node *np = of_cpu_device_node_get(cpu); + struct device_node *prev = NULL; + unsigned int levels = 0, leaves, level; + + leaves = of_count_cache_leaves(np); + if (leaves > 0) + levels = 1; + + prev = np; + while ((np = of_find_next_cache_node(np))) { + of_node_put(prev); + prev = np; + if (!of_device_is_compatible(np, "cache")) + goto err_out; + if (of_property_read_u32(np, "cache-level", &level)) + goto err_out; + if (level <= levels) + goto err_out; + + leaves += of_count_cache_leaves(np); + levels = level; + } + + of_node_put(np); + this_cpu_ci->num_levels = levels; + this_cpu_ci->num_leaves = leaves; + + return 0; + +err_out: + of_node_put(np); + return -EINVAL; +} + #else static inline int cache_setup_of_node(unsigned int cpu) { return 0; } +int init_of_cache_level(unsigned int cpu) { return 0; } #endif int __weak cache_setup_acpi(unsigned int cpu) @@ -256,7 +319,7 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cacheinfo *this_leaf, *sib_leaf; - unsigned int index; + unsigned int index, sib_index; int ret = 0; if (this_cpu_ci->cpu_map_populated) @@ -284,11 +347,13 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) if (i == cpu || !sib_cpu_ci->info_list) continue;/* skip if itself or no cacheinfo */ - - sib_leaf = per_cpu_cacheinfo_idx(i, index); - if (cache_leaves_are_shared(this_leaf, sib_leaf)) { - cpumask_set_cpu(cpu, &sib_leaf->shared_cpu_map); - cpumask_set_cpu(i, &this_leaf->shared_cpu_map); + for (sib_index = 0; sib_index < cache_leaves(i); sib_index++) { + sib_leaf = per_cpu_cacheinfo_idx(i, sib_index); + if (cache_leaves_are_shared(this_leaf, sib_leaf)) { + cpumask_set_cpu(cpu, &sib_leaf->shared_cpu_map); + cpumask_set_cpu(i, &this_leaf->shared_cpu_map); + break; + } } } /* record the maximum cache line size */ @@ -302,7 +367,7 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) static void cache_shared_cpu_map_remove(unsigned int cpu) { struct cacheinfo *this_leaf, *sib_leaf; - unsigned int sibling, index; + unsigned int sibling, index, sib_index; for (index = 0; index < cache_leaves(cpu); index++) { this_leaf = per_cpu_cacheinfo_idx(cpu, index); @@ -313,9 +378,14 @@ static void cache_shared_cpu_map_remove(unsigned int cpu) if (sibling == cpu || !sib_cpu_ci->info_list) continue;/* skip if itself or no cacheinfo */ - sib_leaf = per_cpu_cacheinfo_idx(sibling, index); - cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map); - cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map); + for (sib_index = 0; sib_index < cache_leaves(sibling); sib_index++) { + sib_leaf = per_cpu_cacheinfo_idx(sibling, sib_index); + if (cache_leaves_are_shared(this_leaf, sib_leaf)) { + cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map); + cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map); + break; + } + } } } } @@ -326,10 +396,6 @@ static void free_cache_attributes(unsigned int cpu) return; cache_shared_cpu_map_remove(cpu); - - kfree(per_cpu_cacheinfo(cpu)); - per_cpu_cacheinfo(cpu) = NULL; - cache_leaves(cpu) = 0; } int __weak init_cache_level(unsigned int cpu) @@ -342,29 +408,71 @@ int __weak populate_cache_leaves(unsigned int cpu) return -ENOENT; } +static inline +int allocate_cache_info(int cpu) +{ + per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu), + sizeof(struct cacheinfo), GFP_ATOMIC); + if (!per_cpu_cacheinfo(cpu)) { + cache_leaves(cpu) = 0; + return -ENOMEM; + } + + return 0; +} + +int fetch_cache_info(unsigned int cpu) +{ + struct cpu_cacheinfo *this_cpu_ci; + unsigned int levels = 0, split_levels = 0; + int ret; + + if (acpi_disabled) { + ret = init_of_cache_level(cpu); + if (ret < 0) + return ret; + } else { + ret = acpi_get_cache_info(cpu, &levels, &split_levels); + if (ret < 0) + return ret; + + this_cpu_ci = get_cpu_cacheinfo(cpu); + this_cpu_ci->num_levels = levels; + /* + * This assumes that: + * - there cannot be any split caches (data/instruction) + * above a unified cache + * - data/instruction caches come by pair + */ + this_cpu_ci->num_leaves = levels + split_levels; + } + if (!cache_leaves(cpu)) + return -ENOENT; + + return allocate_cache_info(cpu); +} + int detect_cache_attributes(unsigned int cpu) { int ret; - /* Since early detection of the cacheinfo is allowed via this - * function and this also gets called as CPU hotplug callbacks via - * cacheinfo_cpu_online, the initialisation can be skipped and only - * CPU maps can be updated as the CPU online status would be update - * if called via cacheinfo_cpu_online path. + /* Since early initialization/allocation of the cacheinfo is allowed + * via fetch_cache_info() and this also gets called as CPU hotplug + * callbacks via cacheinfo_cpu_online, the init/alloc can be skipped + * as it will happen only once (the cacheinfo memory is never freed). + * Just populate the cacheinfo. */ if (per_cpu_cacheinfo(cpu)) - goto update_cpu_map; + goto populate_leaves; if (init_cache_level(cpu) || !cache_leaves(cpu)) return -ENOENT; - per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu), - sizeof(struct cacheinfo), GFP_ATOMIC); - if (per_cpu_cacheinfo(cpu) == NULL) { - cache_leaves(cpu) = 0; - return -ENOMEM; - } + ret = allocate_cache_info(cpu); + if (ret) + return ret; +populate_leaves: /* * populate_cache_leaves() may completely setup the cache leaves and * shared_cpu_map or it may leave it partially setup. @@ -373,7 +481,6 @@ int detect_cache_attributes(unsigned int cpu) if (ret) goto free_ci; -update_cpu_map: /* * For systems using DT for cache hierarchy, fw_token * and shared_cpu_map will be set up here only if they are diff --git a/drivers/base/class.c b/drivers/base/class.c index 86ec554cfe60..2373b3e210d8 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -53,6 +53,8 @@ static void class_release(struct kobject *kobj) pr_debug("class '%s': release.\n", class->name); + class->p = NULL; + if (class->class_release) class->class_release(class); else @@ -64,7 +66,7 @@ static void class_release(struct kobject *kobj) static const struct kobj_ns_type_operations *class_child_ns_type(const struct kobject *kobj) { - struct subsys_private *cp = to_subsys_private(kobj); + const struct subsys_private *cp = to_subsys_private(kobj); struct class *class = cp->class; return class->ns_type; @@ -75,7 +77,7 @@ static const struct sysfs_ops class_sysfs_ops = { .store = class_attr_store, }; -static struct kobj_type class_ktype = { +static const struct kobj_type class_ktype = { .sysfs_ops = &class_sysfs_ops, .release = class_release, .child_ns_type = class_child_ns_type, @@ -97,6 +99,7 @@ int class_create_file_ns(struct class *cls, const struct class_attribute *attr, error = -EINVAL; return error; } +EXPORT_SYMBOL_GPL(class_create_file_ns); void class_remove_file_ns(struct class *cls, const struct class_attribute *attr, const void *ns) @@ -104,6 +107,7 @@ void class_remove_file_ns(struct class *cls, const struct class_attribute *attr, if (cls) sysfs_remove_file_ns(&cls->p->subsys.kobj, &attr->attr, ns); } +EXPORT_SYMBOL_GPL(class_remove_file_ns); static struct class *class_get(struct class *cls) { @@ -186,17 +190,21 @@ int __class_register(struct class *cls, struct lock_class_key *key) cls->p = cp; error = kset_register(&cp->subsys); - if (error) { - kfree(cp); - return error; - } + if (error) + goto err_out; + error = class_add_groups(class_get(cls), cls->class_groups); class_put(cls); if (error) { kobject_del(&cp->subsys.kobj); kfree_const(cp->subsys.kobj.name); - kfree(cp); + goto err_out; } + return 0; + +err_out: + kfree(cp); + cls->p = NULL; return error; } EXPORT_SYMBOL_GPL(__class_register); @@ -207,6 +215,7 @@ void class_unregister(struct class *cls) class_remove_groups(cls, cls->class_groups); kset_unregister(&cls->p->subsys); } +EXPORT_SYMBOL_GPL(class_unregister); static void class_create_release(struct class *cls) { @@ -270,6 +279,7 @@ void class_destroy(struct class *cls) class_unregister(cls); } +EXPORT_SYMBOL_GPL(class_destroy); /** * class_dev_iter_init - initialize class device iterator @@ -454,6 +464,7 @@ int class_interface_register(struct class_interface *class_intf) return 0; } +EXPORT_SYMBOL_GPL(class_interface_register); void class_interface_unregister(struct class_interface *class_intf) { @@ -476,6 +487,7 @@ void class_interface_unregister(struct class_interface *class_intf) class_put(parent); } +EXPORT_SYMBOL_GPL(class_interface_unregister); ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr, char *buf) @@ -582,11 +594,3 @@ int __init classes_init(void) return -ENOMEM; return 0; } - -EXPORT_SYMBOL_GPL(class_create_file_ns); -EXPORT_SYMBOL_GPL(class_remove_file_ns); -EXPORT_SYMBOL_GPL(class_unregister); -EXPORT_SYMBOL_GPL(class_destroy); - -EXPORT_SYMBOL_GPL(class_interface_register); -EXPORT_SYMBOL_GPL(class_interface_unregister); diff --git a/drivers/base/component.c b/drivers/base/component.c index 5eadeac6c532..7dbf14a1d915 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -125,7 +125,7 @@ static void component_debugfs_add(struct aggregate_device *m) static void component_debugfs_del(struct aggregate_device *m) { - debugfs_remove(debugfs_lookup(dev_name(m->parent), component_debugfs_dir)); + debugfs_lookup_and_remove(dev_name(m->parent), component_debugfs_dir); } #else diff --git a/drivers/base/core.c b/drivers/base/core.c index bb36aca8d1b7..e54a10b5dbd7 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -54,11 +54,12 @@ static LIST_HEAD(deferred_sync); static unsigned int defer_sync_state_count = 1; static DEFINE_MUTEX(fwnode_link_lock); static bool fw_devlink_is_permissive(void); +static void __fw_devlink_link_to_consumers(struct device *dev); static bool fw_devlink_drv_reg_done; static bool fw_devlink_best_effort; /** - * fwnode_link_add - Create a link between two fwnode_handles. + * __fwnode_link_add - Create a link between two fwnode_handles. * @con: Consumer end of the link. * @sup: Supplier end of the link. * @@ -74,35 +75,42 @@ static bool fw_devlink_best_effort; * Attempts to create duplicate links between the same pair of fwnode handles * are ignored and there is no reference counting. */ -int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup) +static int __fwnode_link_add(struct fwnode_handle *con, + struct fwnode_handle *sup, u8 flags) { struct fwnode_link *link; - int ret = 0; - - mutex_lock(&fwnode_link_lock); list_for_each_entry(link, &sup->consumers, s_hook) - if (link->consumer == con) - goto out; + if (link->consumer == con) { + link->flags |= flags; + return 0; + } link = kzalloc(sizeof(*link), GFP_KERNEL); - if (!link) { - ret = -ENOMEM; - goto out; - } + if (!link) + return -ENOMEM; link->supplier = sup; INIT_LIST_HEAD(&link->s_hook); link->consumer = con; INIT_LIST_HEAD(&link->c_hook); + link->flags = flags; list_add(&link->s_hook, &sup->consumers); list_add(&link->c_hook, &con->suppliers); pr_debug("%pfwP Linked as a fwnode consumer to %pfwP\n", con, sup); -out: - mutex_unlock(&fwnode_link_lock); + return 0; +} + +int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup) +{ + int ret; + + mutex_lock(&fwnode_link_lock); + ret = __fwnode_link_add(con, sup, 0); + mutex_unlock(&fwnode_link_lock); return ret; } @@ -122,6 +130,19 @@ static void __fwnode_link_del(struct fwnode_link *link) } /** + * __fwnode_link_cycle - Mark a fwnode link as being part of a cycle. + * @link: the fwnode_link to be marked + * + * The fwnode_link_lock needs to be held when this function is called. + */ +static void __fwnode_link_cycle(struct fwnode_link *link) +{ + pr_debug("%pfwf: Relaxing link with %pfwf\n", + link->consumer, link->supplier); + link->flags |= FWLINK_FLAG_CYCLE; +} + +/** * fwnode_links_purge_suppliers - Delete all supplier links of fwnode_handle. * @fwnode: fwnode whose supplier links need to be deleted * @@ -181,6 +202,51 @@ void fw_devlink_purge_absent_suppliers(struct fwnode_handle *fwnode) } EXPORT_SYMBOL_GPL(fw_devlink_purge_absent_suppliers); +/** + * __fwnode_links_move_consumers - Move consumer from @from to @to fwnode_handle + * @from: move consumers away from this fwnode + * @to: move consumers to this fwnode + * + * Move all consumer links from @from fwnode to @to fwnode. + */ +static void __fwnode_links_move_consumers(struct fwnode_handle *from, + struct fwnode_handle *to) +{ + struct fwnode_link *link, *tmp; + + list_for_each_entry_safe(link, tmp, &from->consumers, s_hook) { + __fwnode_link_add(link->consumer, to, link->flags); + __fwnode_link_del(link); + } +} + +/** + * __fw_devlink_pickup_dangling_consumers - Pick up dangling consumers + * @fwnode: fwnode from which to pick up dangling consumers + * @new_sup: fwnode of new supplier + * + * If the @fwnode has a corresponding struct device and the device supports + * probing (that is, added to a bus), then we want to let fw_devlink create + * MANAGED device links to this device, so leave @fwnode and its descendant's + * fwnode links alone. + * + * Otherwise, move its consumers to the new supplier @new_sup. + */ +static void __fw_devlink_pickup_dangling_consumers(struct fwnode_handle *fwnode, + struct fwnode_handle *new_sup) +{ + struct fwnode_handle *child; + + if (fwnode->dev && fwnode->dev->bus) + return; + + fwnode->flags |= FWNODE_FLAG_NOT_DEVICE; + __fwnode_links_move_consumers(fwnode, new_sup); + + fwnode_for_each_available_child_node(fwnode, child) + __fw_devlink_pickup_dangling_consumers(child, new_sup); +} + static DEFINE_MUTEX(device_links_lock); DEFINE_STATIC_SRCU(device_links_srcu); @@ -230,6 +296,12 @@ static bool device_is_ancestor(struct device *dev, struct device *target) return false; } +static inline bool device_link_flag_is_sync_state_only(u32 flags) +{ + return (flags & ~(DL_FLAG_INFERRED | DL_FLAG_CYCLE)) == + (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED); +} + /** * device_is_dependent - Check if one device depends on another one * @dev: Device to check dependencies for. @@ -256,8 +328,7 @@ int device_is_dependent(struct device *dev, void *target) return ret; list_for_each_entry(link, &dev->links.consumers, s_node) { - if ((link->flags & ~DL_FLAG_INFERRED) == - (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) + if (device_link_flag_is_sync_state_only(link->flags)) continue; if (link->consumer == target) @@ -330,8 +401,7 @@ static int device_reorder_to_tail(struct device *dev, void *not_used) device_for_each_child(dev, NULL, device_reorder_to_tail); list_for_each_entry(link, &dev->links.consumers, s_node) { - if ((link->flags & ~DL_FLAG_INFERRED) == - (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) + if (device_link_flag_is_sync_state_only(link->flags)) continue; device_reorder_to_tail(link->consumer, NULL); } @@ -592,7 +662,8 @@ postcore_initcall(devlink_class_init); DL_FLAG_AUTOREMOVE_SUPPLIER | \ DL_FLAG_AUTOPROBE_CONSUMER | \ DL_FLAG_SYNC_STATE_ONLY | \ - DL_FLAG_INFERRED) + DL_FLAG_INFERRED | \ + DL_FLAG_CYCLE) #define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \ DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE) @@ -661,8 +732,6 @@ struct device_link *device_link_add(struct device *consumer, if (!consumer || !supplier || consumer == supplier || flags & ~DL_ADD_VALID_FLAGS || (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || - (flags & DL_FLAG_SYNC_STATE_ONLY && - (flags & ~DL_FLAG_INFERRED) != DL_FLAG_SYNC_STATE_ONLY) || (flags & DL_FLAG_AUTOPROBE_CONSUMER && flags & (DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER))) @@ -678,6 +747,10 @@ struct device_link *device_link_add(struct device *consumer, if (!(flags & DL_FLAG_STATELESS)) flags |= DL_FLAG_MANAGED; + if (flags & DL_FLAG_SYNC_STATE_ONLY && + !device_link_flag_is_sync_state_only(flags)) + return NULL; + device_links_write_lock(); device_pm_lock(); @@ -942,6 +1015,21 @@ static bool dev_is_best_effort(struct device *dev) (dev->fwnode && (dev->fwnode->flags & FWNODE_FLAG_BEST_EFFORT)); } +static struct fwnode_handle *fwnode_links_check_suppliers( + struct fwnode_handle *fwnode) +{ + struct fwnode_link *link; + + if (!fwnode || fw_devlink_is_permissive()) + return NULL; + + list_for_each_entry(link, &fwnode->suppliers, c_hook) + if (!(link->flags & FWLINK_FLAG_CYCLE)) + return link->supplier; + + return NULL; +} + /** * device_links_check_suppliers - Check presence of supplier drivers. * @dev: Consumer device. @@ -969,11 +1057,8 @@ int device_links_check_suppliers(struct device *dev) * probe. */ mutex_lock(&fwnode_link_lock); - if (dev->fwnode && !list_empty(&dev->fwnode->suppliers) && - !fw_devlink_is_permissive()) { - sup_fw = list_first_entry(&dev->fwnode->suppliers, - struct fwnode_link, - c_hook)->supplier; + sup_fw = fwnode_links_check_suppliers(dev->fwnode); + if (sup_fw) { if (!dev_is_best_effort(dev)) { fwnode_ret = -EPROBE_DEFER; dev_err_probe(dev, -EPROBE_DEFER, @@ -1162,7 +1247,9 @@ static ssize_t waiting_for_supplier_show(struct device *dev, bool val; device_lock(dev); - val = !list_empty(&dev->fwnode->suppliers); + mutex_lock(&fwnode_link_lock); + val = !!fwnode_links_check_suppliers(dev->fwnode); + mutex_unlock(&fwnode_link_lock); device_unlock(dev); return sysfs_emit(buf, "%u\n", val); } @@ -1225,16 +1312,23 @@ void device_links_driver_bound(struct device *dev) * them. So, fw_devlink no longer needs to create device links to any * of the device's suppliers. * - * Also, if a child firmware node of this bound device is not added as - * a device by now, assume it is never going to be added and make sure - * other devices don't defer probe indefinitely by waiting for such a - * child device. + * Also, if a child firmware node of this bound device is not added as a + * device by now, assume it is never going to be added. Make this bound + * device the fallback supplier to the dangling consumers of the child + * firmware node because this bound device is probably implementing the + * child firmware node functionality and we don't want the dangling + * consumers to defer probe indefinitely waiting for a device for the + * child firmware node. */ if (dev->fwnode && dev->fwnode->dev == dev) { struct fwnode_handle *child; fwnode_links_purge_suppliers(dev->fwnode); + mutex_lock(&fwnode_link_lock); fwnode_for_each_available_child_node(dev->fwnode, child) - fw_devlink_purge_absent_suppliers(child); + __fw_devlink_pickup_dangling_consumers(child, + dev->fwnode); + __fw_devlink_link_to_consumers(dev); + mutex_unlock(&fwnode_link_lock); } device_remove_file(dev, &dev_attr_waiting_for_supplier); @@ -1591,8 +1685,11 @@ static int __init fw_devlink_strict_setup(char *arg) } early_param("fw_devlink.strict", fw_devlink_strict_setup); -u32 fw_devlink_get_flags(void) +static inline u32 fw_devlink_get_flags(u8 fwlink_flags) { + if (fwlink_flags & FWLINK_FLAG_CYCLE) + return FW_DEVLINK_FLAGS_PERMISSIVE | DL_FLAG_CYCLE; + return fw_devlink_flags; } @@ -1630,7 +1727,7 @@ static void fw_devlink_relax_link(struct device_link *link) if (!(link->flags & DL_FLAG_INFERRED)) return; - if (link->flags == (DL_FLAG_MANAGED | FW_DEVLINK_FLAGS_PERMISSIVE)) + if (device_link_flag_is_sync_state_only(link->flags)) return; pm_runtime_drop_link(link); @@ -1727,44 +1824,138 @@ static void fw_devlink_unblock_consumers(struct device *dev) device_links_write_unlock(); } + +static bool fwnode_init_without_drv(struct fwnode_handle *fwnode) +{ + struct device *dev; + bool ret; + + if (!(fwnode->flags & FWNODE_FLAG_INITIALIZED)) + return false; + + dev = get_dev_from_fwnode(fwnode); + ret = !dev || dev->links.status == DL_DEV_NO_DRIVER; + put_device(dev); + + return ret; +} + +static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode) +{ + struct fwnode_handle *parent; + + fwnode_for_each_parent_node(fwnode, parent) { + if (fwnode_init_without_drv(parent)) { + fwnode_handle_put(parent); + return true; + } + } + + return false; +} + /** - * fw_devlink_relax_cycle - Convert cyclic links to SYNC_STATE_ONLY links - * @con: Device to check dependencies for. - * @sup: Device to check against. - * - * Check if @sup depends on @con or any device dependent on it (its child or - * its consumer etc). When such a cyclic dependency is found, convert all - * device links created solely by fw_devlink into SYNC_STATE_ONLY device links. - * This is the equivalent of doing fw_devlink=permissive just between the - * devices in the cycle. We need to do this because, at this point, fw_devlink - * can't tell which of these dependencies is not a real dependency. - * - * Return 1 if a cycle is found. Otherwise, return 0. + * __fw_devlink_relax_cycles - Relax and mark dependency cycles. + * @con: Potential consumer device. + * @sup_handle: Potential supplier's fwnode. + * + * Needs to be called with fwnode_lock and device link lock held. + * + * Check if @sup_handle or any of its ancestors or suppliers direct/indirectly + * depend on @con. This function can detect multiple cyles between @sup_handle + * and @con. When such dependency cycles are found, convert all device links + * created solely by fw_devlink into SYNC_STATE_ONLY device links. Also, mark + * all fwnode links in the cycle with FWLINK_FLAG_CYCLE so that when they are + * converted into a device link in the future, they are created as + * SYNC_STATE_ONLY device links. This is the equivalent of doing + * fw_devlink=permissive just between the devices in the cycle. We need to do + * this because, at this point, fw_devlink can't tell which of these + * dependencies is not a real dependency. + * + * Return true if one or more cycles were found. Otherwise, return false. */ -static int fw_devlink_relax_cycle(struct device *con, void *sup) +static bool __fw_devlink_relax_cycles(struct device *con, + struct fwnode_handle *sup_handle) { - struct device_link *link; - int ret; + struct device *sup_dev = NULL, *par_dev = NULL; + struct fwnode_link *link; + struct device_link *dev_link; + bool ret = false; - if (con == sup) - return 1; + if (!sup_handle) + return false; - ret = device_for_each_child(con, sup, fw_devlink_relax_cycle); - if (ret) - return ret; + /* + * We aren't trying to find all cycles. Just a cycle between con and + * sup_handle. + */ + if (sup_handle->flags & FWNODE_FLAG_VISITED) + return false; - list_for_each_entry(link, &con->links.consumers, s_node) { - if ((link->flags & ~DL_FLAG_INFERRED) == - (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) - continue; + sup_handle->flags |= FWNODE_FLAG_VISITED; - if (!fw_devlink_relax_cycle(link->consumer, sup)) - continue; + sup_dev = get_dev_from_fwnode(sup_handle); - ret = 1; + /* Termination condition. */ + if (sup_dev == con) { + ret = true; + goto out; + } - fw_devlink_relax_link(link); + /* + * If sup_dev is bound to a driver and @con hasn't started binding to a + * driver, sup_dev can't be a consumer of @con. So, no need to check + * further. + */ + if (sup_dev && sup_dev->links.status == DL_DEV_DRIVER_BOUND && + con->links.status == DL_DEV_NO_DRIVER) { + ret = false; + goto out; + } + + list_for_each_entry(link, &sup_handle->suppliers, c_hook) { + if (__fw_devlink_relax_cycles(con, link->supplier)) { + __fwnode_link_cycle(link); + ret = true; + } } + + /* + * Give priority to device parent over fwnode parent to account for any + * quirks in how fwnodes are converted to devices. + */ + if (sup_dev) + par_dev = get_device(sup_dev->parent); + else + par_dev = fwnode_get_next_parent_dev(sup_handle); + + if (par_dev && __fw_devlink_relax_cycles(con, par_dev->fwnode)) + ret = true; + + if (!sup_dev) + goto out; + + list_for_each_entry(dev_link, &sup_dev->links.suppliers, c_node) { + /* + * Ignore a SYNC_STATE_ONLY flag only if it wasn't marked as + * such due to a cycle. + */ + if (device_link_flag_is_sync_state_only(dev_link->flags) && + !(dev_link->flags & DL_FLAG_CYCLE)) + continue; + + if (__fw_devlink_relax_cycles(con, + dev_link->supplier->fwnode)) { + fw_devlink_relax_link(dev_link); + dev_link->flags |= DL_FLAG_CYCLE; + ret = true; + } + } + +out: + sup_handle->flags &= ~FWNODE_FLAG_VISITED; + put_device(sup_dev); + put_device(par_dev); return ret; } @@ -1772,7 +1963,7 @@ static int fw_devlink_relax_cycle(struct device *con, void *sup) * fw_devlink_create_devlink - Create a device link from a consumer to fwnode * @con: consumer device for the device link * @sup_handle: fwnode handle of supplier - * @flags: devlink flags + * @link: fwnode link that's being converted to a device link * * This function will try to create a device link between the consumer device * @con and the supplier device represented by @sup_handle. @@ -1789,10 +1980,17 @@ static int fw_devlink_relax_cycle(struct device *con, void *sup) * possible to do that in the future */ static int fw_devlink_create_devlink(struct device *con, - struct fwnode_handle *sup_handle, u32 flags) + struct fwnode_handle *sup_handle, + struct fwnode_link *link) { struct device *sup_dev; int ret = 0; + u32 flags; + + if (con->fwnode == link->consumer) + flags = fw_devlink_get_flags(link->flags); + else + flags = FW_DEVLINK_FLAGS_PERMISSIVE; /* * In some cases, a device P might also be a supplier to its child node @@ -1813,7 +2011,26 @@ static int fw_devlink_create_devlink(struct device *con, fwnode_is_ancestor_of(sup_handle, con->fwnode)) return -EINVAL; - sup_dev = get_dev_from_fwnode(sup_handle); + /* + * SYNC_STATE_ONLY device links don't block probing and supports cycles. + * So cycle detection isn't necessary and shouldn't be done. + */ + if (!(flags & DL_FLAG_SYNC_STATE_ONLY)) { + device_links_write_lock(); + if (__fw_devlink_relax_cycles(con, sup_handle)) { + __fwnode_link_cycle(link); + flags = fw_devlink_get_flags(link->flags); + dev_info(con, "Fixed dependency cycle(s) with %pfwf\n", + sup_handle); + } + device_links_write_unlock(); + } + + if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE) + sup_dev = fwnode_get_next_parent_dev(sup_handle); + else + sup_dev = get_dev_from_fwnode(sup_handle); + if (sup_dev) { /* * If it's one of those drivers that don't actually bind to @@ -1822,71 +2039,34 @@ static int fw_devlink_create_devlink(struct device *con, */ if (sup_dev->links.status == DL_DEV_NO_DRIVER && sup_handle->flags & FWNODE_FLAG_INITIALIZED) { + dev_dbg(con, + "Not linking %pfwf - dev might never probe\n", + sup_handle); ret = -EINVAL; goto out; } - /* - * If this fails, it is due to cycles in device links. Just - * give up on this link and treat it as invalid. - */ - if (!device_link_add(con, sup_dev, flags) && - !(flags & DL_FLAG_SYNC_STATE_ONLY)) { - dev_info(con, "Fixing up cyclic dependency with %s\n", - dev_name(sup_dev)); - device_links_write_lock(); - fw_devlink_relax_cycle(con, sup_dev); - device_links_write_unlock(); - device_link_add(con, sup_dev, - FW_DEVLINK_FLAGS_PERMISSIVE); + if (!device_link_add(con, sup_dev, flags)) { + dev_err(con, "Failed to create device link with %s\n", + dev_name(sup_dev)); ret = -EINVAL; } goto out; } - /* Supplier that's already initialized without a struct device. */ - if (sup_handle->flags & FWNODE_FLAG_INITIALIZED) - return -EINVAL; - - /* - * DL_FLAG_SYNC_STATE_ONLY doesn't block probing and supports - * cycles. So cycle detection isn't necessary and shouldn't be - * done. - */ - if (flags & DL_FLAG_SYNC_STATE_ONLY) - return -EAGAIN; - /* - * If we can't find the supplier device from its fwnode, it might be - * due to a cyclic dependency between fwnodes. Some of these cycles can - * be broken by applying logic. Check for these types of cycles and - * break them so that devices in the cycle probe properly. - * - * If the supplier's parent is dependent on the consumer, then the - * consumer and supplier have a cyclic dependency. Since fw_devlink - * can't tell which of the inferred dependencies are incorrect, don't - * enforce probe ordering between any of the devices in this cyclic - * dependency. Do this by relaxing all the fw_devlink device links in - * this cycle and by treating the fwnode link between the consumer and - * the supplier as an invalid dependency. + * Supplier or supplier's ancestor already initialized without a struct + * device or being probed by a driver. */ - sup_dev = fwnode_get_next_parent_dev(sup_handle); - if (sup_dev && device_is_dependent(con, sup_dev)) { - dev_info(con, "Fixing up cyclic dependency with %pfwP (%s)\n", - sup_handle, dev_name(sup_dev)); - device_links_write_lock(); - fw_devlink_relax_cycle(con, sup_dev); - device_links_write_unlock(); - ret = -EINVAL; - } else { - /* - * Can't check for cycles or no cycles. So let's try - * again later. - */ - ret = -EAGAIN; + if (fwnode_init_without_drv(sup_handle) || + fwnode_ancestor_init_without_drv(sup_handle)) { + dev_dbg(con, "Not linking %pfwf - might never become dev\n", + sup_handle); + return -EINVAL; } + ret = -EAGAIN; out: put_device(sup_dev); return ret; @@ -1914,7 +2094,6 @@ static void __fw_devlink_link_to_consumers(struct device *dev) struct fwnode_link *link, *tmp; list_for_each_entry_safe(link, tmp, &fwnode->consumers, s_hook) { - u32 dl_flags = fw_devlink_get_flags(); struct device *con_dev; bool own_link = true; int ret; @@ -1944,14 +2123,13 @@ static void __fw_devlink_link_to_consumers(struct device *dev) con_dev = NULL; } else { own_link = false; - dl_flags = FW_DEVLINK_FLAGS_PERMISSIVE; } } if (!con_dev) continue; - ret = fw_devlink_create_devlink(con_dev, fwnode, dl_flags); + ret = fw_devlink_create_devlink(con_dev, fwnode, link); put_device(con_dev); if (!own_link || ret == -EAGAIN) continue; @@ -1971,10 +2149,7 @@ static void __fw_devlink_link_to_consumers(struct device *dev) * * The function creates normal (non-SYNC_STATE_ONLY) device links between @dev * and the real suppliers of @dev. Once these device links are created, the - * fwnode links are deleted. When such device links are successfully created, - * this function is called recursively on those supplier devices. This is - * needed to detect and break some invalid cycles in fwnode links. See - * fw_devlink_create_devlink() for more details. + * fwnode links are deleted. * * In addition, it also looks at all the suppliers of the entire fwnode tree * because some of the child devices of @dev that have not been added yet @@ -1992,44 +2167,16 @@ static void __fw_devlink_link_to_suppliers(struct device *dev, bool own_link = (dev->fwnode == fwnode); struct fwnode_link *link, *tmp; struct fwnode_handle *child = NULL; - u32 dl_flags; - - if (own_link) - dl_flags = fw_devlink_get_flags(); - else - dl_flags = FW_DEVLINK_FLAGS_PERMISSIVE; list_for_each_entry_safe(link, tmp, &fwnode->suppliers, c_hook) { int ret; - struct device *sup_dev; struct fwnode_handle *sup = link->supplier; - ret = fw_devlink_create_devlink(dev, sup, dl_flags); + ret = fw_devlink_create_devlink(dev, sup, link); if (!own_link || ret == -EAGAIN) continue; __fwnode_link_del(link); - - /* If no device link was created, nothing more to do. */ - if (ret) - continue; - - /* - * If a device link was successfully created to a supplier, we - * now need to try and link the supplier to all its suppliers. - * - * This is needed to detect and delete false dependencies in - * fwnode links that haven't been converted to a device link - * yet. See comments in fw_devlink_create_devlink() for more - * details on the false dependency. - * - * Without deleting these false dependencies, some devices will - * never probe because they'll keep waiting for their false - * dependency fwnode links to be converted to device links. - */ - sup_dev = get_dev_from_fwnode(sup); - __fw_devlink_link_to_suppliers(sup_dev, sup_dev->fwnode); - put_device(sup_dev); } /* @@ -2312,7 +2459,7 @@ static void device_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t dev->class->get_ownership(dev, uid, gid); } -static struct kobj_type device_ktype = { +static const struct kobj_type device_ktype = { .release = device_release, .sysfs_ops = &dev_sysfs_ops, .namespace = device_namespace, @@ -2345,9 +2492,9 @@ static const char *dev_uevent_name(const struct kobject *kobj) return NULL; } -static int dev_uevent(struct kobject *kobj, struct kobj_uevent_env *env) +static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env) { - struct device *dev = kobj_to_dev(kobj); + const struct device *dev = kobj_to_dev(kobj); int retval = 0; /* add device node properties if present */ @@ -2950,7 +3097,7 @@ struct kobj_ns_type_operations *class_dir_child_ns_type(const struct kobject *ko return dir->class->ns_type; } -static struct kobj_type class_dir_ktype = { +static const struct kobj_type class_dir_ktype = { .release = class_dir_release, .sysfs_ops = &kobj_sysfs_ops, .child_ns_type = class_dir_child_ns_type @@ -2984,8 +3131,9 @@ static DEFINE_MUTEX(gdp_mutex); static struct kobject *get_device_parent(struct device *dev, struct device *parent) { + struct kobject *kobj = NULL; + if (dev->class) { - struct kobject *kobj = NULL; struct kobject *parent_kobj; struct kobject *k; @@ -3033,8 +3181,15 @@ static struct kobject *get_device_parent(struct device *dev, } /* subsystems can specify a default root directory for their devices */ - if (!parent && dev->bus && dev->bus->dev_root) - return &dev->bus->dev_root->kobj; + if (!parent && dev->bus) { + struct device *dev_root = bus_get_dev_root(dev->bus); + + if (dev_root) { + kobj = &dev_root->kobj; + put_device(dev_root); + return kobj; + } + } if (parent) return &parent->kobj; @@ -3371,7 +3526,7 @@ int device_add(struct device *dev) /* we require the name to be set before, and pass NULL */ error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); if (error) { - glue_dir = get_glue_dir(dev); + glue_dir = kobj; goto Error; } @@ -3411,10 +3566,7 @@ int device_add(struct device *dev) /* Notify clients of device addition. This call must come * after dpm_sysfs_add() and before kobject_uevent(). */ - if (dev->bus) - blocking_notifier_call_chain(&dev->bus->p->bus_notifier, - BUS_NOTIFY_ADD_DEVICE, dev); - + bus_notify(dev, BUS_NOTIFY_ADD_DEVICE); kobject_uevent(&dev->kobj, KOBJ_ADD); /* @@ -3471,6 +3623,7 @@ done: device_pm_remove(dev); dpm_sysfs_remove(dev); DPMError: + dev->driver = NULL; bus_remove_device(dev); BusError: device_remove_attrs(dev); @@ -3594,9 +3747,7 @@ void device_del(struct device *dev) * before dpm_sysfs_remove(). */ noio_flag = memalloc_noio_save(); - if (dev->bus) - blocking_notifier_call_chain(&dev->bus->p->bus_notifier, - BUS_NOTIFY_DEL_DEVICE, dev); + bus_notify(dev, BUS_NOTIFY_DEL_DEVICE); dpm_sysfs_remove(dev); if (parent) @@ -3627,9 +3778,7 @@ void device_del(struct device *dev) device_platform_notify_remove(dev); device_links_purge(dev); - if (dev->bus) - blocking_notifier_call_chain(&dev->bus->p->bus_notifier, - BUS_NOTIFY_REMOVED_DEVICE, dev); + bus_notify(dev, BUS_NOTIFY_REMOVED_DEVICE); kobject_uevent(&dev->kobj, KOBJ_REMOVE); glue_dir = get_glue_dir(dev); kobject_del(&dev->kobj); @@ -3697,7 +3846,7 @@ static struct device *next_device(struct klist_iter *i) * a name. This memory is returned in tmp and needs to be * freed by the caller. */ -const char *device_get_devnode(struct device *dev, +const char *device_get_devnode(const struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid, const char **tmp) { diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 4c98849577d4..182c6122f815 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -125,17 +125,6 @@ static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store); #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ #endif /* CONFIG_HOTPLUG_CPU */ -struct bus_type cpu_subsys = { - .name = "cpu", - .dev_name = "cpu", - .match = cpu_subsys_match, -#ifdef CONFIG_HOTPLUG_CPU - .online = cpu_subsys_online, - .offline = cpu_subsys_offline, -#endif -}; -EXPORT_SYMBOL_GPL(cpu_subsys); - #ifdef CONFIG_KEXEC #include <linux/kexec.h> @@ -336,7 +325,7 @@ static ssize_t print_cpu_modalias(struct device *dev, return len; } -static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) +static int cpu_uevent(const struct device *dev, struct kobj_uevent_env *env) { char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); if (buf) { @@ -348,6 +337,20 @@ static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) } #endif +struct bus_type cpu_subsys = { + .name = "cpu", + .dev_name = "cpu", + .match = cpu_subsys_match, +#ifdef CONFIG_HOTPLUG_CPU + .online = cpu_subsys_online, + .offline = cpu_subsys_offline, +#endif +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE + .uevent = cpu_uevent, +#endif +}; +EXPORT_SYMBOL_GPL(cpu_subsys); + /* * register_cpu - Setup a sysfs device for a CPU. * @cpu - cpu->hotpluggable field set to 1 will generate a control file in @@ -368,9 +371,6 @@ int register_cpu(struct cpu *cpu, int num) cpu->dev.offline_disabled = !cpu->hotpluggable; cpu->dev.offline = !cpu_online(num); cpu->dev.of_node = of_get_cpu_node(num, NULL); -#ifdef CONFIG_GENERIC_CPU_AUTOPROBE - cpu->dev.bus->uevent = cpu_uevent; -#endif cpu->dev.groups = common_cpu_attr_groups; if (cpu->hotpluggable) cpu->dev.groups = hotplugable_cpu_attr_groups; @@ -610,9 +610,13 @@ static const struct attribute_group cpu_root_vulnerabilities_group = { static void __init cpu_register_vulnerabilities(void) { - if (sysfs_create_group(&cpu_subsys.dev_root->kobj, - &cpu_root_vulnerabilities_group)) - pr_err("Unable to register CPU vulnerabilities\n"); + struct device *dev = bus_get_dev_root(&cpu_subsys); + + if (dev) { + if (sysfs_create_group(&dev->kobj, &cpu_root_vulnerabilities_group)) + pr_err("Unable to register CPU vulnerabilities\n"); + put_device(dev); + } } #else diff --git a/drivers/base/dd.c b/drivers/base/dd.c index e9b2f9c25efe..8def2ba08a82 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -257,13 +257,11 @@ static int deferred_devs_show(struct seq_file *s, void *data) DEFINE_SHOW_ATTRIBUTE(deferred_devs); #ifdef CONFIG_MODULES -int driver_deferred_probe_timeout = 10; +static int driver_deferred_probe_timeout = 10; #else -int driver_deferred_probe_timeout; +static int driver_deferred_probe_timeout; #endif -EXPORT_SYMBOL_GPL(driver_deferred_probe_timeout); - static int __init deferred_probe_timeout_setup(char *str) { int timeout; @@ -372,7 +370,7 @@ late_initcall(deferred_probe_initcall); static void __exit deferred_probe_exit(void) { - debugfs_remove_recursive(debugfs_lookup("devices_deferred", NULL)); + debugfs_lookup_and_remove("devices_deferred", NULL); } __exitcall(deferred_probe_exit); @@ -413,10 +411,7 @@ static void driver_bound(struct device *dev) driver_deferred_probe_del(dev); driver_deferred_probe_trigger(); - if (dev->bus) - blocking_notifier_call_chain(&dev->bus->p->bus_notifier, - BUS_NOTIFY_BOUND_DRIVER, dev); - + bus_notify(dev, BUS_NOTIFY_BOUND_DRIVER); kobject_uevent(&dev->kobj, KOBJ_BIND); } @@ -435,9 +430,7 @@ static int driver_sysfs_add(struct device *dev) { int ret; - if (dev->bus) - blocking_notifier_call_chain(&dev->bus->p->bus_notifier, - BUS_NOTIFY_BIND_DRIVER, dev); + bus_notify(dev, BUS_NOTIFY_BIND_DRIVER); ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj, kobject_name(&dev->kobj)); @@ -502,9 +495,8 @@ int device_bind_driver(struct device *dev) device_links_force_bind(dev); driver_bound(dev); } - else if (dev->bus) - blocking_notifier_call_chain(&dev->bus->p->bus_notifier, - BUS_NOTIFY_DRIVER_NOT_BOUND, dev); + else + bus_notify(dev, BUS_NOTIFY_DRIVER_NOT_BOUND); return ret; } EXPORT_SYMBOL_GPL(device_bind_driver); @@ -695,9 +687,7 @@ dev_groups_failed: probe_failed: driver_sysfs_remove(dev); sysfs_failed: - if (dev->bus) - blocking_notifier_call_chain(&dev->bus->p->bus_notifier, - BUS_NOTIFY_DRIVER_NOT_BOUND, dev); + bus_notify(dev, BUS_NOTIFY_DRIVER_NOT_BOUND); if (dev->bus && dev->bus->dma_cleanup) dev->bus->dma_cleanup(dev); pinctrl_bind_failed: @@ -1243,10 +1233,7 @@ static void __device_release_driver(struct device *dev, struct device *parent) driver_sysfs_remove(dev); - if (dev->bus) - blocking_notifier_call_chain(&dev->bus->p->bus_notifier, - BUS_NOTIFY_UNBIND_DRIVER, - dev); + bus_notify(dev, BUS_NOTIFY_UNBIND_DRIVER); pm_runtime_put_sync(dev); @@ -1260,11 +1247,8 @@ static void __device_release_driver(struct device *dev, struct device *parent) klist_remove(&dev->p->knode_driver); device_pm_check_callbacks(dev); - if (dev->bus) - blocking_notifier_call_chain(&dev->bus->p->bus_notifier, - BUS_NOTIFY_UNBOUND_DRIVER, - dev); + bus_notify(dev, BUS_NOTIFY_UNBOUND_DRIVER); kobject_uevent(&dev->kobj, KOBJ_UNBIND); } } diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 03e8a95f1f35..ae72d4ba8547 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -13,6 +13,8 @@ * overwrite the default setting if needed. */ +#define pr_fmt(fmt) "devtmpfs: " fmt + #include <linux/kernel.h> #include <linux/syscalls.h> #include <linux/mount.h> @@ -376,9 +378,9 @@ int __init devtmpfs_mount(void) err = init_mount("devtmpfs", "dev", "devtmpfs", DEVTMPFS_MFLAGS, NULL); if (err) - printk(KERN_INFO "devtmpfs: error mounting %i\n", err); + pr_info("error mounting %d\n", err); else - printk(KERN_INFO "devtmpfs: mounted\n"); + pr_info("mounted\n"); return err; } @@ -460,14 +462,12 @@ int __init devtmpfs_init(void) mnt = vfs_kern_mount(&internal_fs_type, 0, "devtmpfs", opts); if (IS_ERR(mnt)) { - printk(KERN_ERR "devtmpfs: unable to create devtmpfs %ld\n", - PTR_ERR(mnt)); + pr_err("unable to create devtmpfs %ld\n", PTR_ERR(mnt)); return PTR_ERR(mnt); } err = register_filesystem(&dev_fs_type); if (err) { - printk(KERN_ERR "devtmpfs: unable to register devtmpfs " - "type %i\n", err); + pr_err("unable to register devtmpfs type %d\n", err); return err; } @@ -480,12 +480,12 @@ int __init devtmpfs_init(void) } if (err) { - printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); + pr_err("unable to create devtmpfs %d\n", err); unregister_filesystem(&dev_fs_type); thread = NULL; return err; } - printk(KERN_INFO "devtmpfs: initialized\n"); + pr_info("initialized\n"); return 0; } diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 676b6275d5b5..c8436c26ed6a 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -224,7 +224,7 @@ int driver_register(struct device_driver *drv) int ret; struct device_driver *other; - if (!drv->bus->p) { + if (!bus_is_registered(drv->bus)) { pr_err("Driver '%s' was unable to register with bus_type '%s' because the bus was not initialized.\n", drv->name, drv->bus->name); return -EINVAL; @@ -274,30 +274,3 @@ void driver_unregister(struct device_driver *drv) bus_remove_driver(drv); } EXPORT_SYMBOL_GPL(driver_unregister); - -/** - * driver_find - locate driver on a bus by its name. - * @name: name of the driver. - * @bus: bus to scan for the driver. - * - * Call kset_find_obj() to iterate over list of drivers on - * a bus to find driver by name. Return driver if found. - * - * This routine provides no locking to prevent the driver it returns - * from being unregistered or unloaded while the caller is using it. - * The caller is responsible for preventing this. - */ -struct device_driver *driver_find(const char *name, struct bus_type *bus) -{ - struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); - struct driver_private *priv; - - if (k) { - /* Drop reference added by kset_find_obj() */ - kobject_put(k); - priv = to_driver(k); - return priv->driver; - } - return NULL; -} -EXPORT_SYMBOL_GPL(driver_find); diff --git a/drivers/base/memory.c b/drivers/base/memory.c index fe98fb8d94e5..b456ac213610 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -115,18 +115,13 @@ unsigned long __weak memory_block_size_bytes(void) } EXPORT_SYMBOL_GPL(memory_block_size_bytes); -/* - * Show the first physical section index (number) of this memory block. - */ +/* Show the memory block ID, relative to the memory block size */ static ssize_t phys_index_show(struct device *dev, struct device_attribute *attr, char *buf) { struct memory_block *mem = to_memory_block(dev); - unsigned long phys_index; - - phys_index = mem->start_section_nr / sections_per_block; - return sysfs_emit(buf, "%08lx\n", phys_index); + return sysfs_emit(buf, "%08lx\n", memory_block_id(mem->start_section_nr)); } /* diff --git a/drivers/base/physical_location.c b/drivers/base/physical_location.c index 87af641cfe1a..951819e71b4a 100644 --- a/drivers/base/physical_location.c +++ b/drivers/base/physical_location.c @@ -24,8 +24,11 @@ bool dev_add_physical_location(struct device *dev) dev->physical_location = kzalloc(sizeof(*dev->physical_location), GFP_KERNEL); - if (!dev->physical_location) + if (!dev->physical_location) { + ACPI_FREE(pld); return false; + } + dev->physical_location->panel = pld->panel; dev->physical_location->vertical_position = pld->vertical_position; dev->physical_location->horizontal_position = pld->horizontal_position; diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 968f3d71eeab..77510e4f47de 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -441,11 +441,9 @@ static int __platform_get_irq_byname(struct platform_device *dev, struct resource *r; int ret; - if (!dev->dev.of_node || IS_ENABLED(CONFIG_OF_IRQ)) { - ret = fwnode_irq_get_byname(dev_fwnode(&dev->dev), name); - if (ret > 0 || ret == -EPROBE_DEFER) - return ret; - } + ret = fwnode_irq_get_byname(dev_fwnode(&dev->dev), name); + if (ret > 0 || ret == -EPROBE_DEFER) + return ret; r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); if (r) { @@ -499,6 +497,8 @@ EXPORT_SYMBOL_GPL(platform_get_irq_byname_optional); * platform_add_devices - add a numbers of platform devices * @devs: array of platform devices to add * @num: number of platform devices in array + * + * Return: 0 on success, negative error number on failure. */ int platform_add_devices(struct platform_device **devs, int num) { @@ -883,6 +883,13 @@ static int platform_probe_fail(struct platform_device *pdev) return -ENXIO; } +static int is_bound_to_driver(struct device *dev, void *driver) +{ + if (dev->driver == driver) + return 1; + return 0; +} + /** * __platform_driver_probe - register driver for non-hotpluggable device * @drv: platform driver structure @@ -906,7 +913,7 @@ static int platform_probe_fail(struct platform_device *pdev) int __init_or_module __platform_driver_probe(struct platform_driver *drv, int (*probe)(struct platform_device *), struct module *module) { - int retval, code; + int retval; if (drv->driver.probe_type == PROBE_PREFER_ASYNCHRONOUS) { pr_err("%s: drivers registered with %s can not be probed asynchronously\n", @@ -932,24 +939,21 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv, /* temporary section violation during probe() */ drv->probe = probe; - retval = code = __platform_driver_register(drv, module); + retval = __platform_driver_register(drv, module); if (retval) return retval; - /* - * Fixup that section violation, being paranoid about code scanning - * the list of drivers in order to probe new devices. Check to see - * if the probe was successful, and make sure any forced probes of - * new devices fail. - */ - spin_lock(&drv->driver.bus->p->klist_drivers.k_lock); + /* Force all new probes of this driver to fail */ drv->probe = platform_probe_fail; - if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) - retval = -ENODEV; - spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock); - if (code != retval) + /* Walk all platform devices and see if any actually bound to this driver. + * If not, return an error as the device should have done so by now. + */ + if (!bus_for_each_dev(&platform_bus_type, NULL, &drv->driver, is_bound_to_driver)) { + retval = -ENODEV; platform_driver_unregister(drv); + } + return retval; } EXPORT_SYMBOL_GPL(__platform_driver_probe); @@ -1353,9 +1357,9 @@ static int platform_match(struct device *dev, struct device_driver *drv) return (strcmp(pdev->name, drv->name) == 0); } -static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) +static int platform_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct platform_device *pdev = to_platform_device(dev); + const struct platform_device *pdev = to_platform_device(dev); int rc; /* Some devices have extra OF data and an OF-style MODALIAS */ @@ -1416,7 +1420,9 @@ static void platform_remove(struct device *_dev) struct platform_driver *drv = to_platform_driver(_dev->driver); struct platform_device *dev = to_platform_device(_dev); - if (drv->remove) { + if (drv->remove_new) { + drv->remove_new(dev); + } else if (drv->remove) { int ret = drv->remove(dev); if (ret) diff --git a/drivers/base/soc.c b/drivers/base/soc.c index 22130b5f789d..0fb1d4ab9d8a 100644 --- a/drivers/base/soc.c +++ b/drivers/base/soc.c @@ -30,6 +30,7 @@ struct soc_device { static struct bus_type soc_bus_type = { .name = "soc", }; +static bool soc_bus_registered; static DEVICE_ATTR(machine, 0444, soc_info_show, NULL); static DEVICE_ATTR(family, 0444, soc_info_show, NULL); @@ -117,7 +118,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr const struct attribute_group **soc_attr_groups; int ret; - if (!soc_bus_type.p) { + if (!soc_bus_registered) { if (early_soc_dev_attr) return ERR_PTR(-EBUSY); early_soc_dev_attr = soc_dev_attr; @@ -183,6 +184,7 @@ static int __init soc_bus_register(void) ret = bus_register(&soc_bus_type); if (ret) return ret; + soc_bus_registered = true; if (early_soc_dev_attr) return PTR_ERR(soc_device_register(early_soc_dev_attr)); diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index 0a482212c7e8..1886995a0b3a 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -760,7 +760,7 @@ static void software_node_release(struct kobject *kobj) kfree(swnode); } -static struct kobj_type software_node_type = { +static const struct kobj_type software_node_type = { .release = software_node_release, .sysfs_ops = &kobj_sysfs_ops, }; @@ -820,67 +820,6 @@ swnode_register(const struct software_node *node, struct swnode *parent, } /** - * software_node_register_nodes - Register an array of software nodes - * @nodes: Zero terminated array of software nodes to be registered - * - * Register multiple software nodes at once. If any node in the array - * has its .parent pointer set (which can only be to another software_node), - * then its parent **must** have been registered before it is; either outside - * of this function or by ordering the array such that parent comes before - * child. - */ -int software_node_register_nodes(const struct software_node *nodes) -{ - int ret; - int i; - - for (i = 0; nodes[i].name; i++) { - const struct software_node *parent = nodes[i].parent; - - if (parent && !software_node_to_swnode(parent)) { - ret = -EINVAL; - goto err_unregister_nodes; - } - - ret = software_node_register(&nodes[i]); - if (ret) - goto err_unregister_nodes; - } - - return 0; - -err_unregister_nodes: - software_node_unregister_nodes(nodes); - return ret; -} -EXPORT_SYMBOL_GPL(software_node_register_nodes); - -/** - * software_node_unregister_nodes - Unregister an array of software nodes - * @nodes: Zero terminated array of software nodes to be unregistered - * - * Unregister multiple software nodes at once. If parent pointers are set up - * in any of the software nodes then the array **must** be ordered such that - * parents come before their children. - * - * NOTE: If you are uncertain whether the array is ordered such that - * parents will be unregistered before their children, it is wiser to - * remove the nodes individually, in the correct order (child before - * parent). - */ -void software_node_unregister_nodes(const struct software_node *nodes) -{ - unsigned int i = 0; - - while (nodes[i].name) - i++; - - while (i--) - software_node_unregister(&nodes[i]); -} -EXPORT_SYMBOL_GPL(software_node_unregister_nodes); - -/** * software_node_register_node_group - Register a group of software nodes * @node_group: NULL terminated array of software node pointers to be registered * diff --git a/drivers/base/test/property-entry-test.c b/drivers/base/test/property-entry-test.c index 6071d5bc128c..dd2b606d76a3 100644 --- a/drivers/base/test/property-entry-test.c +++ b/drivers/base/test/property-entry-test.c @@ -405,20 +405,18 @@ static void pe_test_move_inline_str(struct kunit *test) /* Handling of reference properties */ static void pe_test_reference(struct kunit *test) { - static const struct software_node nodes[] = { - { .name = "1", }, - { .name = "2", }, - { } - }; + static const struct software_node node1 = { .name = "1" }; + static const struct software_node node2 = { .name = "2" }; + static const struct software_node *group[] = { &node1, &node2, NULL }; static const struct software_node_ref_args refs[] = { - SOFTWARE_NODE_REFERENCE(&nodes[0]), - SOFTWARE_NODE_REFERENCE(&nodes[1], 3, 4), + SOFTWARE_NODE_REFERENCE(&node1), + SOFTWARE_NODE_REFERENCE(&node2, 3, 4), }; const struct property_entry entries[] = { - PROPERTY_ENTRY_REF("ref-1", &nodes[0]), - PROPERTY_ENTRY_REF("ref-2", &nodes[1], 1, 2), + PROPERTY_ENTRY_REF("ref-1", &node1), + PROPERTY_ENTRY_REF("ref-2", &node2, 1, 2), PROPERTY_ENTRY_REF_ARRAY("ref-3", refs), { } }; @@ -427,7 +425,7 @@ static void pe_test_reference(struct kunit *test) struct fwnode_reference_args ref; int error; - error = software_node_register_nodes(nodes); + error = software_node_register_node_group(group); KUNIT_ASSERT_EQ(test, error, 0); node = fwnode_create_software_node(entries, NULL); @@ -436,7 +434,7 @@ static void pe_test_reference(struct kunit *test) error = fwnode_property_get_reference_args(node, "ref-1", NULL, 0, 0, &ref); KUNIT_ASSERT_EQ(test, error, 0); - KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[0]); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &node1); KUNIT_EXPECT_EQ(test, ref.nargs, 0U); /* wrong index */ @@ -447,7 +445,7 @@ static void pe_test_reference(struct kunit *test) error = fwnode_property_get_reference_args(node, "ref-2", NULL, 1, 0, &ref); KUNIT_ASSERT_EQ(test, error, 0); - KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[1]); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &node2); KUNIT_EXPECT_EQ(test, ref.nargs, 1U); KUNIT_EXPECT_EQ(test, ref.args[0], 1LLU); @@ -455,7 +453,7 @@ static void pe_test_reference(struct kunit *test) error = fwnode_property_get_reference_args(node, "ref-2", NULL, 3, 0, &ref); KUNIT_ASSERT_EQ(test, error, 0); - KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[1]); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &node2); KUNIT_EXPECT_EQ(test, ref.nargs, 3U); KUNIT_EXPECT_EQ(test, ref.args[0], 1LLU); KUNIT_EXPECT_EQ(test, ref.args[1], 2LLU); @@ -470,14 +468,14 @@ static void pe_test_reference(struct kunit *test) error = fwnode_property_get_reference_args(node, "ref-3", NULL, 0, 0, &ref); KUNIT_ASSERT_EQ(test, error, 0); - KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[0]); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &node1); KUNIT_EXPECT_EQ(test, ref.nargs, 0U); /* second reference in the array */ error = fwnode_property_get_reference_args(node, "ref-3", NULL, 2, 1, &ref); KUNIT_ASSERT_EQ(test, error, 0); - KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[1]); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &node2); KUNIT_EXPECT_EQ(test, ref.nargs, 2U); KUNIT_EXPECT_EQ(test, ref.args[0], 3LLU); KUNIT_EXPECT_EQ(test, ref.args[1], 4LLU); @@ -488,7 +486,7 @@ static void pe_test_reference(struct kunit *test) KUNIT_EXPECT_NE(test, error, 0); fwnode_remove_software_node(node); - software_node_unregister_nodes(nodes); + software_node_unregister_node_group(group); } static struct kunit_case property_entry_test_cases[] = { diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c index ccc86206e508..09ee2a1e35bb 100644 --- a/drivers/base/transport_class.c +++ b/drivers/base/transport_class.c @@ -155,12 +155,27 @@ static int transport_add_class_device(struct attribute_container *cont, struct device *dev, struct device *classdev) { + struct transport_class *tclass = class_to_transport_class(cont->class); int error = attribute_container_add_class_device(classdev); struct transport_container *tcont = attribute_container_to_transport_container(cont); - if (!error && tcont->statistics) + if (error) + goto err_remove; + + if (tcont->statistics) { error = sysfs_create_group(&classdev->kobj, tcont->statistics); + if (error) + goto err_del; + } + + return 0; + +err_del: + attribute_container_class_device_del(classdev); +err_remove: + if (tclass->remove) + tclass->remove(tcont, dev, classdev); return error; } diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 0a8469e0b13a..7b39f010bbb3 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -28,7 +28,7 @@ static DEFINE_MUTEX(bcma_buses_mutex); static int bcma_bus_match(struct device *dev, struct device_driver *drv); static int bcma_device_probe(struct device *dev); static void bcma_device_remove(struct device *dev); -static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env); +static int bcma_device_uevent(const struct device *dev, struct kobj_uevent_env *env); static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -627,9 +627,9 @@ static void bcma_device_remove(struct device *dev) put_device(dev); } -static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int bcma_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct bcma_device *core = container_of(dev, struct bcma_device, dev); + const struct bcma_device *core = container_of_const(dev, struct bcma_device, dev); return add_uevent_var(env, "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X", diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 774f307844b4..36cb091a33b4 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -124,9 +124,9 @@ out: /* * fsl_mc_bus_uevent - callback invoked when a device is added */ -static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int fsl_mc_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + const struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s", mc_dev->obj_desc.vendor, diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c index dffe03658ff9..a6a48e515478 100644 --- a/drivers/bus/mhi/ep/main.c +++ b/drivers/bus/mhi/ep/main.c @@ -1550,9 +1550,9 @@ void mhi_ep_driver_unregister(struct mhi_ep_driver *mhi_drv) } EXPORT_SYMBOL_GPL(mhi_ep_driver_unregister); -static int mhi_ep_uevent(struct device *dev, struct kobj_uevent_env *env) +static int mhi_ep_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct mhi_ep_device *mhi_dev = to_mhi_ep_device(dev); + const struct mhi_ep_device *mhi_dev = to_mhi_ep_device(dev); return add_uevent_var(env, "MODALIAS=" MHI_EP_DEVICE_MODALIAS_FMT, mhi_dev->name); diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c index 7307335c4fd1..3d779ee6396d 100644 --- a/drivers/bus/mhi/host/init.c +++ b/drivers/bus/mhi/host/init.c @@ -1395,9 +1395,9 @@ void mhi_driver_unregister(struct mhi_driver *mhi_drv) } EXPORT_SYMBOL_GPL(mhi_driver_unregister); -static int mhi_uevent(struct device *dev, struct kobj_uevent_env *env) +static int mhi_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct mhi_device *mhi_dev = to_mhi_device(dev); + const struct mhi_device *mhi_dev = to_mhi_device(dev); return add_uevent_var(env, "MODALIAS=" MHI_DEVICE_MODALIAS_FMT, mhi_dev->name); diff --git a/drivers/bus/mips_cdmm.c b/drivers/bus/mips_cdmm.c index fca0d0669aa9..554e1992edd4 100644 --- a/drivers/bus/mips_cdmm.c +++ b/drivers/bus/mips_cdmm.c @@ -67,9 +67,9 @@ static int mips_cdmm_match(struct device *dev, struct device_driver *drv) return mips_cdmm_lookup(cdrv->id_table, cdev) != NULL; } -static int mips_cdmm_uevent(struct device *dev, struct kobj_uevent_env *env) +static int mips_cdmm_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct mips_cdmm_device *cdev = to_mips_cdmm_device(dev); + const struct mips_cdmm_device *cdev = to_mips_cdmm_device(dev); int retval = 0; retval = add_uevent_var(env, "CDMM_CPU=%u", cdev->cpu); diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 226e87b85116..696c0aefb0ca 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -172,12 +172,17 @@ static void sunxi_rsb_device_remove(struct device *dev) drv->remove(to_sunxi_rsb_device(dev)); } +static int sunxi_rsb_device_modalias(const struct device *dev, struct kobj_uevent_env *env) +{ + return of_device_uevent_modalias(dev, env); +} + static struct bus_type sunxi_rsb_bus = { .name = RSB_CTRL_NAME, .match = sunxi_rsb_device_match, .probe = sunxi_rsb_device_probe, .remove = sunxi_rsb_device_remove, - .uevent = of_device_uevent_modalias, + .uevent = sunxi_rsb_device_modalias, }; static void sunxi_rsb_dev_release(struct device *dev) diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index a74a93310d26..b75dd77df7ce 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -27,7 +27,7 @@ static void cxl_memdev_release(struct device *dev) kfree(cxlmd); } -static char *cxl_memdev_devnode(struct device *dev, umode_t *mode, kuid_t *uid, +static char *cxl_memdev_devnode(const struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid) { return kasprintf(GFP_KERNEL, "cxl/%s", dev_name(dev)); @@ -162,7 +162,7 @@ static const struct device_type cxl_memdev_type = { .groups = cxl_memdev_attribute_groups, }; -bool is_cxl_memdev(struct device *dev) +bool is_cxl_memdev(const struct device *dev) { return dev->type == &cxl_memdev_type; } diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index b631a0520456..3f02dc135a12 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -38,7 +38,7 @@ static ssize_t devtype_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(devtype); -static int cxl_device_id(struct device *dev) +static int cxl_device_id(const struct device *dev) { if (dev->type == &cxl_nvdimm_bridge_type) return CXL_DEVICE_NVDIMM_BRIDGE; @@ -523,13 +523,13 @@ static const struct device_type cxl_port_type = { .groups = cxl_port_attribute_groups, }; -bool is_cxl_port(struct device *dev) +bool is_cxl_port(const struct device *dev) { return dev->type == &cxl_port_type; } EXPORT_SYMBOL_NS_GPL(is_cxl_port, CXL); -struct cxl_port *to_cxl_port(struct device *dev) +struct cxl_port *to_cxl_port(const struct device *dev) { if (dev_WARN_ONCE(dev, dev->type != &cxl_port_type, "not a cxl_port device\n")) @@ -1826,7 +1826,7 @@ void cxl_driver_unregister(struct cxl_driver *cxl_drv) } EXPORT_SYMBOL_NS_GPL(cxl_driver_unregister, CXL); -static int cxl_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int cxl_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { return add_uevent_var(env, "MODALIAS=" CXL_MODALIAS_FMT, cxl_device_id(dev)); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 1b1cf459ac77..c9e1b48a1a53 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -588,8 +588,8 @@ static inline bool is_cxl_root(struct cxl_port *port) return port->uport == port->dev.parent; } -bool is_cxl_port(struct device *dev); -struct cxl_port *to_cxl_port(struct device *dev); +bool is_cxl_port(const struct device *dev); +struct cxl_port *to_cxl_port(const struct device *dev); struct pci_bus; int devm_cxl_register_pci_bus(struct device *host, struct device *uport, struct pci_bus *bus); diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index ab138004f644..6749f2afb1b7 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -72,7 +72,7 @@ cxled_to_memdev(struct cxl_endpoint_decoder *cxled) return to_cxl_memdev(port->uport); } -bool is_cxl_memdev(struct device *dev); +bool is_cxl_memdev(const struct device *dev); static inline bool is_cxl_endpoint(struct cxl_port *port) { return is_cxl_memdev(port->uport); diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c index 1dad813ee4a6..e3a384182fe7 100644 --- a/drivers/dax/bus.c +++ b/drivers/dax/bus.c @@ -18,7 +18,7 @@ struct dax_id { char dev_name[DAX_NAME_LEN]; }; -static int dax_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int dax_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { /* * We only ever expect to handle device-dax instances, i.e. the diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 65bffde137e3..713582cc27d1 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -127,9 +127,9 @@ static int eisa_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int eisa_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int eisa_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct eisa_device *edev = to_eisa_device(dev); + const struct eisa_device *edev = to_eisa_device(dev); add_uevent_var(env, "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig); return 0; diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index adddd8c45d0c..aa597cda0d88 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -133,7 +133,7 @@ static void get_ids(const u32 *directory, int *id) } } -static void get_modalias_ids(struct fw_unit *unit, int *id) +static void get_modalias_ids(const struct fw_unit *unit, int *id) { get_ids(&fw_parent_device(unit)->config_rom[5], id); get_ids(unit->directory, id); @@ -195,7 +195,7 @@ static void fw_unit_remove(struct device *dev) driver->remove(fw_unit(dev)); } -static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) +static int get_modalias(const struct fw_unit *unit, char *buffer, size_t buffer_size) { int id[] = {0, 0, 0, 0}; @@ -206,9 +206,9 @@ static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) id[0], id[1], id[2], id[3]); } -static int fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) +static int fw_unit_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct fw_unit *unit = fw_unit(dev); + const struct fw_unit *unit = fw_unit(dev); char modalias[64]; get_modalias(unit, modalias, sizeof(modalias)); diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c index 99d439480612..f29d77ecf72d 100644 --- a/drivers/firmware/arm_ffa/bus.c +++ b/drivers/firmware/arm_ffa/bus.c @@ -56,9 +56,9 @@ static void ffa_device_remove(struct device *dev) ffa_drv->remove(to_ffa_dev(dev)); } -static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct ffa_device *ffa_dev = to_ffa_dev(dev); + const struct ffa_device *ffa_dev = to_ffa_dev(dev); return add_uevent_var(env, "MODALIAS=arm_ffa:%04x:%pUb", ffa_dev->vm_id, &ffa_dev->uuid); diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index 35bb70724d44..cc2eba067575 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/device.h> +#include <linux/of.h> #include "common.h" @@ -191,7 +192,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol, scmi_dev->id = id; scmi_dev->protocol_id = protocol; scmi_dev->dev.parent = parent; - scmi_dev->dev.of_node = np; + device_set_node(&scmi_dev->dev, of_fwnode_handle(np)); scmi_dev->dev.bus = &scmi_bus_type; scmi_dev->dev.release = scmi_device_release; dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id); diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index b010f0a83a78..dd7a783d53b5 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -294,9 +294,9 @@ static void dfl_bus_remove(struct device *dev) ddrv->remove(ddev); } -static int dfl_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int dfl_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct dfl_device *ddev = to_dfl_dev(dev); + const struct dfl_device *ddev = to_dfl_dev(dev); return add_uevent_var(env, "MODALIAS=dfl:t%04Xf%04X", ddev->type, ddev->feature_id); diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c index 694e80c06665..0b927c9f4267 100644 --- a/drivers/fsi/fsi-core.c +++ b/drivers/fsi/fsi-core.c @@ -897,10 +897,10 @@ static const struct attribute_group *cfam_attr_groups[] = { NULL, }; -static char *cfam_devnode(struct device *dev, umode_t *mode, +static char *cfam_devnode(const struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid) { - struct fsi_slave *slave = to_fsi_slave(dev); + const struct fsi_slave *slave = to_fsi_slave(dev); #ifdef CONFIG_FSI_NEW_DEV_NODE return kasprintf(GFP_KERNEL, "fsi/cfam%d", slave->cdev_idx); @@ -915,7 +915,7 @@ static const struct device_type cfam_type = { .groups = cfam_attr_groups }; -static char *fsi_cdev_devnode(struct device *dev, umode_t *mode, +static char *fsi_cdev_devnode(const struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid) { #ifdef CONFIG_FSI_NEW_DEV_NODE diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 99a2c77c3711..19bd23044b01 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -587,6 +587,13 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) { int ret; + /* + * If fwnode doesn't belong to another device, it's safe to clear its + * initialized flag. + */ + if (gdev->dev.fwnode && !gdev->dev.fwnode->dev) + fwnode_dev_initialized(gdev->dev.fwnode, false); + ret = gcdev_register(gdev, gpio_devt); if (ret) return ret; diff --git a/drivers/gpu/drm/display/drm_dp_aux_bus.c b/drivers/gpu/drm/display/drm_dp_aux_bus.c index f5741b45ca07..8a165be1a821 100644 --- a/drivers/gpu/drm/display/drm_dp_aux_bus.c +++ b/drivers/gpu/drm/display/drm_dp_aux_bus.c @@ -161,9 +161,14 @@ static void dp_aux_ep_dev_release(struct device *dev) kfree(aux_ep_with_data); } +static int dp_aux_ep_dev_modalias(const struct device *dev, struct kobj_uevent_env *env) +{ + return of_device_uevent_modalias(dev, env); +} + static struct device_type dp_aux_device_type_type = { .groups = dp_aux_ep_dev_groups, - .uevent = of_device_uevent_modalias, + .uevent = dp_aux_ep_dev_modalias, .release = dp_aux_ep_dev_release, }; diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 4bc15fbd009d..b41aaf2bb9f1 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -62,9 +62,9 @@ static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv) return 0; } -static int mipi_dsi_uevent(struct device *dev, struct kobj_uevent_env *env) +static int mipi_dsi_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); + const struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); int err; err = of_device_uevent_modalias(dev, env); diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index bdee16a0bb8e..bc7271a00a94 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -338,7 +338,7 @@ static int host1x_device_match(struct device *dev, struct device_driver *drv) return strcmp(dev_name(dev), drv->name) == 0; } -static int host1x_device_uevent(struct device *dev, +static int host1x_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { struct device_node *np = dev->parent->of_node; diff --git a/drivers/greybus/core.c b/drivers/greybus/core.c index e546c6431877..5714be740470 100644 --- a/drivers/greybus/core.c +++ b/drivers/greybus/core.c @@ -78,14 +78,14 @@ static int greybus_match_device(struct device *dev, struct device_driver *drv) return 0; } -static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int greybus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct gb_host_device *hd; - struct gb_module *module = NULL; - struct gb_interface *intf = NULL; - struct gb_control *control = NULL; - struct gb_bundle *bundle = NULL; - struct gb_svc *svc = NULL; + const struct gb_host_device *hd; + const struct gb_module *module = NULL; + const struct gb_interface *intf = NULL; + const struct gb_control *control = NULL; + const struct gb_bundle *bundle = NULL; + const struct gb_svc *svc = NULL; if (is_gb_host_device(dev)) { hd = to_gb_host_device(dev); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1ee623c26c49..842afc88a949 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2676,9 +2676,9 @@ static const struct attribute_group hid_dev_group = { }; __ATTRIBUTE_GROUPS(hid_dev); -static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) +static int hid_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct hid_device *hdev = to_hid_device(dev); + const struct hid_device *hdev = to_hid_device(dev); if (add_uevent_var(env, "HID_ID=%04X:%08X:%08X", hdev->bus, hdev->vendor, hdev->product)) diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c index f68aba8794fe..81385ab37fa9 100644 --- a/drivers/hid/intel-ish-hid/ishtp/bus.c +++ b/drivers/hid/intel-ish-hid/ishtp/bus.c @@ -361,7 +361,7 @@ static struct attribute *ishtp_cl_dev_attrs[] = { }; ATTRIBUTE_GROUPS(ishtp_cl_dev); -static int ishtp_cl_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ishtp_cl_uevent(const struct device *dev, struct kobj_uevent_env *env) { if (add_uevent_var(env, "MODALIAS=" ISHTP_MODULE_PREFIX "%s", dev_name(dev))) return -ENOMEM; diff --git a/drivers/hsi/hsi_core.c b/drivers/hsi/hsi_core.c index 884066109699..8fda8f1d064d 100644 --- a/drivers/hsi/hsi_core.c +++ b/drivers/hsi/hsi_core.c @@ -30,7 +30,7 @@ static struct attribute *hsi_bus_dev_attrs[] = { }; ATTRIBUTE_GROUPS(hsi_bus_dev); -static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int hsi_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev)); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 1901556efe79..d24dd65b33d4 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -711,9 +711,9 @@ __ATTRIBUTE_GROUPS(vmbus_bus); * representation of the device guid (each byte of the guid will be * represented with two hex characters. */ -static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) +static int vmbus_uevent(const struct device *device, struct kobj_uevent_env *env) { - struct hv_device *dev = device_to_hv_device(device); + const struct hv_device *dev = device_to_hv_device(device); const char *format = "MODALIAS=vmbus:%*phN"; return add_uevent_var(env, format, UUID_SIZE, &dev->dev_type); diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index 7e753a75d23b..cc7f879bb175 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -185,11 +185,11 @@ static struct device_type intel_th_source_device_type = { .release = intel_th_device_release, }; -static char *intel_th_output_devnode(struct device *dev, umode_t *mode, +static char *intel_th_output_devnode(const struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid) { - struct intel_th_device *thdev = to_intel_th_device(dev); - struct intel_th *th = to_intel_th(thdev); + const struct intel_th_device *thdev = to_intel_th_device(dev); + const struct intel_th *th = to_intel_th(thdev); char *node; if (thdev->id >= 0) diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h index 0ffb42990175..6cbba733f259 100644 --- a/drivers/hwtracing/intel_th/intel_th.h +++ b/drivers/hwtracing/intel_th/intel_th.h @@ -205,7 +205,7 @@ struct intel_th_driver { * INTEL_TH_SWITCH and INTEL_TH_SOURCE are children of the intel_th device. */ static inline struct intel_th_device * -to_intel_th_parent(struct intel_th_device *thdev) +to_intel_th_parent(const struct intel_th_device *thdev) { struct device *parent = thdev->dev.parent; @@ -215,7 +215,7 @@ to_intel_th_parent(struct intel_th_device *thdev) return to_intel_th_device(parent); } -static inline struct intel_th *to_intel_th(struct intel_th_device *thdev) +static inline struct intel_th *to_intel_th(const struct intel_th_device *thdev) { if (thdev->type == INTEL_TH_OUTPUT) thdev = to_intel_th_parent(thdev); diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index b47e255fc6f1..734d8e6ad4a9 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -136,9 +136,9 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) return 0; } -static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int i2c_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct i2c_client *client = to_i2c_client(dev); + const struct i2c_client *client = to_i2c_client(dev); int rc; rc = of_device_uevent_modalias(dev, env); diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c index 9762630b917e..1a6a8703dbc3 100644 --- a/drivers/i3c/device.c +++ b/drivers/i3c/device.c @@ -78,7 +78,7 @@ EXPORT_SYMBOL_GPL(i3c_device_do_setdasa); * * Retrieve I3C dev info. */ -void i3c_device_get_info(struct i3c_device *dev, +void i3c_device_get_info(const struct i3c_device *dev, struct i3c_device_info *info) { if (!info) @@ -209,18 +209,6 @@ struct device *i3cdev_to_dev(struct i3c_device *i3cdev) EXPORT_SYMBOL_GPL(i3cdev_to_dev); /** - * dev_to_i3cdev() - Returns the I3C device containing @dev - * @dev: device object - * - * Return: a pointer to an I3C device object. - */ -struct i3c_device *dev_to_i3cdev(struct device *dev) -{ - return container_of(dev, struct i3c_device, dev); -} -EXPORT_SYMBOL_GPL(dev_to_i3cdev); - -/** * i3c_device_match_id() - Returns the i3c_device_id entry matching @i3cdev * @i3cdev: I3C device * @id_table: I3C device match table diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index d7e6f6c99aea..7a60e1c5e587 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -273,9 +273,9 @@ static struct attribute *i3c_device_attrs[] = { }; ATTRIBUTE_GROUPS(i3c_device); -static int i3c_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int i3c_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct i3c_device *i3cdev = dev_to_i3cdev(dev); + const struct i3c_device *i3cdev = dev_to_i3cdev(dev); struct i3c_device_info devinfo; u16 manuf, part, ext; diff --git a/drivers/input/input.c b/drivers/input/input.c index ca2e3dd7188b..0336e799d713 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1372,7 +1372,7 @@ INPUT_DEV_STRING_ATTR_SHOW(phys); INPUT_DEV_STRING_ATTR_SHOW(uniq); static int input_print_modalias_bits(char *buf, int size, - char name, unsigned long *bm, + char name, const unsigned long *bm, unsigned int min_bit, unsigned int max_bit) { int len = 0, i; @@ -1384,7 +1384,7 @@ static int input_print_modalias_bits(char *buf, int size, return len; } -static int input_print_modalias(char *buf, int size, struct input_dev *id, +static int input_print_modalias(char *buf, int size, const struct input_dev *id, int add_cr) { int len; @@ -1432,7 +1432,7 @@ static ssize_t input_dev_show_modalias(struct device *dev, } static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); -static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, +static int input_print_bitmap(char *buf, int buf_size, const unsigned long *bitmap, int max, int add_cr); static ssize_t input_dev_show_properties(struct device *dev, @@ -1524,7 +1524,7 @@ static const struct attribute_group input_dev_id_attr_group = { .attrs = input_dev_id_attrs, }; -static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, +static int input_print_bitmap(char *buf, int buf_size, const unsigned long *bitmap, int max, int add_cr) { int i; @@ -1621,7 +1621,7 @@ static void input_dev_release(struct device *device) * device bitfields. */ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, - const char *name, unsigned long *bitmap, int max) + const char *name, const unsigned long *bitmap, int max) { int len; @@ -1639,7 +1639,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, } static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, - struct input_dev *dev) + const struct input_dev *dev) { int len; @@ -1677,9 +1677,9 @@ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, return err; \ } while (0) -static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) +static int input_dev_uevent(const struct device *device, struct kobj_uevent_env *env) { - struct input_dev *dev = to_input_dev(device); + const struct input_dev *dev = to_input_dev(device); INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x", dev->id.bustype, dev->id.vendor, diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 15ce3202322f..767fc9efb4a8 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -895,9 +895,9 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv) return err; \ } while (0) -static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) +static int serio_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct serio *serio; + const struct serio *serio; if (!dev) return -ENODEV; diff --git a/drivers/ipack/ipack.c b/drivers/ipack/ipack.c index 74d449858a61..cc1ecfd49928 100644 --- a/drivers/ipack/ipack.c +++ b/drivers/ipack/ipack.c @@ -76,9 +76,9 @@ static void ipack_bus_remove(struct device *device) drv->ops->remove(dev); } -static int ipack_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ipack_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct ipack_device *idev; + const struct ipack_device *idev; if (!dev) return -ENODEV; diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c index b9c22f764b4d..8a0e82067924 100644 --- a/drivers/irqchip/irq-imx-gpcv2.c +++ b/drivers/irqchip/irq-imx-gpcv2.c @@ -283,6 +283,7 @@ static int __init imx_gpcv2_irqchip_init(struct device_node *node, * later the GPC power domain driver will not be skipped. */ of_node_clear_flag(node, OF_POPULATED); + fwnode_dev_initialized(domain->fwnode, false); return 0; } diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 3bc1f374e657..211ed9aa9edc 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -128,12 +128,17 @@ static int macio_device_resume(struct device * dev) return 0; } +static int macio_device_modalias(const struct device *dev, struct kobj_uevent_env *env) +{ + return of_device_uevent_modalias(dev, env); +} + extern const struct attribute_group *macio_dev_groups[]; struct bus_type macio_bus_type = { .name = "macio", .match = macio_bus_match, - .uevent = of_device_uevent_modalias, + .uevent = macio_device_modalias, .probe = macio_device_probe, .remove = macio_device_remove, .shutdown = macio_device_shutdown, diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c index b8ad4f16b4ac..978fdfc19a06 100644 --- a/drivers/mcb/mcb-core.c +++ b/drivers/mcb/mcb-core.c @@ -41,9 +41,9 @@ static int mcb_match(struct device *dev, struct device_driver *drv) return 0; } -static int mcb_uevent(struct device *dev, struct kobj_uevent_env *env) +static int mcb_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct mcb_device *mdev = to_mcb_device(dev); + const struct mcb_device *mdev = to_mcb_device(dev); int ret; ret = add_uevent_var(env, "MODALIAS=mcb:16z%03d", mdev->id); diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index df6c94da2f6a..dfefe0d8aa95 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -195,6 +195,19 @@ static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor) SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */ } +static void cio2_bridge_init_swnode_group(struct cio2_sensor *sensor) +{ + struct software_node *nodes = sensor->swnodes; + + sensor->group[SWNODE_SENSOR_HID] = &nodes[SWNODE_SENSOR_HID]; + sensor->group[SWNODE_SENSOR_PORT] = &nodes[SWNODE_SENSOR_PORT]; + sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT]; + sensor->group[SWNODE_CIO2_PORT] = &nodes[SWNODE_CIO2_PORT]; + sensor->group[SWNODE_CIO2_ENDPOINT] = &nodes[SWNODE_CIO2_ENDPOINT]; + if (sensor->ssdb.vcmtype) + sensor->group[SWNODE_VCM] = &nodes[SWNODE_VCM]; +} + static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, struct cio2_sensor *sensor) { @@ -219,6 +232,8 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, if (sensor->ssdb.vcmtype) nodes[SWNODE_VCM] = NODE_VCM(cio2_vcm_types[sensor->ssdb.vcmtype - 1]); + + cio2_bridge_init_swnode_group(sensor); } static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor) @@ -252,7 +267,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) for (i = 0; i < bridge->n_sensors; i++) { sensor = &bridge->sensors[i]; - software_node_unregister_nodes(sensor->swnodes); + software_node_unregister_node_group(sensor->group); ACPI_FREE(sensor->pld); acpi_dev_put(sensor->adev); i2c_unregister_device(sensor->vcm_i2c_client); @@ -263,7 +278,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, struct cio2_bridge *bridge, struct pci_dev *cio2) { - struct fwnode_handle *fwnode; + struct fwnode_handle *fwnode, *primary; struct cio2_sensor *sensor; struct acpi_device *adev; acpi_status status; @@ -310,7 +325,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, cio2_bridge_create_fwnode_properties(sensor, bridge, cfg); cio2_bridge_create_connection_swnodes(bridge, sensor); - ret = software_node_register_nodes(sensor->swnodes); + ret = software_node_register_node_group(sensor->group); if (ret) goto err_free_pld; @@ -322,7 +337,9 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, } sensor->adev = acpi_dev_get(adev); - adev->fwnode.secondary = fwnode; + + primary = acpi_fwnode_handle(adev); + primary->secondary = fwnode; cio2_bridge_instantiate_vcm_i2c_client(sensor); @@ -335,7 +352,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, return 0; err_free_swnodes: - software_node_unregister_nodes(sensor->swnodes); + software_node_unregister_node_group(sensor->group); err_free_pld: ACPI_FREE(sensor->pld); err_put_adev: diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h index 4418cbd08208..b93b749c65bd 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h @@ -117,8 +117,9 @@ struct cio2_sensor { struct acpi_device *adev; struct i2c_client *vcm_i2c_client; - /* SWNODE_COUNT + 1 for terminating empty node */ - struct software_node swnodes[SWNODE_COUNT + 1]; + /* SWNODE_COUNT + 1 for terminating NULL */ + const struct software_node *group[SWNODE_COUNT + 1]; + struct software_node swnodes[SWNODE_COUNT]; struct cio2_node_names node_names; struct cio2_sensor_ssdb ssdb; diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 527d9324742b..6bdad6341844 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1614,7 +1614,7 @@ static void rc_dev_release(struct device *device) kfree(dev); } -static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) +static int rc_dev_uevent(const struct device *device, struct kobj_uevent_env *env) { struct rc_dev *dev = to_rc_dev(device); int ret = 0; diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index 660df7d269fa..bf7667845459 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -57,10 +57,10 @@ static int memstick_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int memstick_uevent(struct device *dev, struct kobj_uevent_env *env) +static int memstick_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct memstick_dev *card = container_of(dev, struct memstick_dev, - dev); + const struct memstick_dev *card = container_of_const(dev, struct memstick_dev, + dev); if (add_uevent_var(env, "MEMSTICK_TYPE=%02X", card->id.type)) return -ENOMEM; diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 71d53d7ffdba..5d7a68674d9b 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -1227,9 +1227,9 @@ ATTRIBUTE_GROUPS(mei_cldev); * * Return: 0 on success -ENOMEM on when add_uevent_var fails */ -static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int mei_cl_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct mei_cl_device *cldev = to_mei_cl_device(dev); + const struct mei_cl_device *cldev = to_mei_cl_device(dev); const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl); u8 version = mei_me_cl_ver(cldev->me_cl); diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index a3098fea3bf7..eee9b6581604 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -55,9 +55,9 @@ static int tifm_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env) +static int tifm_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); + const struct tifm_dev *sock = container_of_const(dev, struct tifm_dev, dev); if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1))) return -ENOMEM; diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 36679f4e9acc..2c3074a605fc 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -55,9 +55,9 @@ static struct attribute *mmc_dev_attrs[] = { ATTRIBUTE_GROUPS(mmc_dev); static int -mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +mmc_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct mmc_card *card = mmc_dev_to_card(dev); + const struct mmc_card *card = mmc_dev_to_card(dev); const char *type; unsigned int i; int retval = 0; diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index f191a2a76f3b..47a48e902a24 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -120,9 +120,9 @@ static int sdio_bus_match(struct device *dev, struct device_driver *drv) } static int -sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +sdio_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct sdio_func *func = dev_to_sdio_func(dev); + const struct sdio_func *func = dev_to_sdio_func(dev); unsigned int i; if (add_uevent_var(env, diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index d442fa94c872..85f5ee6f06fc 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -577,6 +577,7 @@ static int mtd_part_of_parse(struct mtd_info *master, { struct mtd_part_parser *parser; struct device_node *np; + struct device_node *child; struct property *prop; struct device *dev; const char *compat; @@ -594,6 +595,15 @@ static int mtd_part_of_parse(struct mtd_info *master, else np = of_get_child_by_name(np, "partitions"); + /* + * Don't create devices that are added to a bus but will never get + * probed. That'll cause fw_devlink to block probing of consumers of + * this partition until the partition device is probed. + */ + for_each_child_of_node(np, child) + if (of_device_is_compatible(child, "nvmem-cells")) + of_node_set_flag(child, OF_POPULATED); + of_property_for_each_string(np, "compatible", prop, compat) { parser = mtd_part_get_compatible_parser(compat); if (!parser) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 00d5bcdf0e6f..389f33a12534 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -1330,7 +1330,7 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int mdio_uevent(struct device *dev, struct kobj_uevent_env *env) +static int mdio_uevent(const struct device *dev, struct kobj_uevent_env *env) { int rc; diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 001636901dda..a78a25b87240 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -200,7 +200,7 @@ static void xenvif_debugfs_delif(struct xenvif *vif) * and vif variables to the environment, for the benefit of the vif-* hotplug * scripts. */ -static int netback_uevent(struct xenbus_device *xdev, +static int netback_uevent(const struct xenbus_device *xdev, struct kobj_uevent_env *env) { struct backend_info *be = dev_get_drvdata(&xdev->dev); diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index b38d0355b0ac..92ce92fc9932 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -28,7 +28,7 @@ static int nvdimm_bus_major; struct class *nd_class; static DEFINE_IDA(nd_ida); -static int to_nd_device_type(struct device *dev) +static int to_nd_device_type(const struct device *dev) { if (is_nvdimm(dev)) return ND_DEVICE_DIMM; @@ -42,7 +42,7 @@ static int to_nd_device_type(struct device *dev) return 0; } -static int nvdimm_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int nvdimm_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { return add_uevent_var(env, "MODALIAS=" ND_DEVICE_MODALIAS_FMT, to_nd_device_type(dev)); diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c index 7f4a9d28b670..3bd61f245788 100644 --- a/drivers/nvdimm/dax_devs.c +++ b/drivers/nvdimm/dax_devs.c @@ -38,7 +38,7 @@ static const struct device_type nd_dax_device_type = { .groups = nd_pfn_attribute_groups, }; -bool is_nd_dax(struct device *dev) +bool is_nd_dax(const struct device *dev) { return dev ? dev->type == &nd_dax_device_type : false; } diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index 1fc081dcf631..fb571666d33b 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -572,7 +572,7 @@ static const struct device_type nvdimm_device_type = { .groups = nvdimm_attribute_groups, }; -bool is_nvdimm(struct device *dev) +bool is_nvdimm(const struct device *dev) { return dev->type == &nvdimm_device_type; } diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h index cc86ee09d7c0..ca2bbc57e755 100644 --- a/drivers/nvdimm/nd-core.h +++ b/drivers/nvdimm/nd-core.h @@ -82,14 +82,14 @@ static inline void nvdimm_security_overwrite_query(struct work_struct *work) } #endif -bool is_nvdimm(struct device *dev); -bool is_nd_pmem(struct device *dev); -bool is_nd_volatile(struct device *dev); -static inline bool is_nd_region(struct device *dev) +bool is_nvdimm(const struct device *dev); +bool is_nd_pmem(const struct device *dev); +bool is_nd_volatile(const struct device *dev); +static inline bool is_nd_region(const struct device *dev) { return is_nd_pmem(dev) || is_nd_volatile(dev); } -static inline bool is_memory(struct device *dev) +static inline bool is_memory(const struct device *dev) { return is_nd_pmem(dev) || is_nd_volatile(dev); } diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index ec5219680092..e8b9d27dbb3c 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -599,7 +599,7 @@ static inline int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) struct nd_dax *to_nd_dax(struct device *dev); #if IS_ENABLED(CONFIG_NVDIMM_DAX) int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns); -bool is_nd_dax(struct device *dev); +bool is_nd_dax(const struct device *dev); struct device *nd_dax_create(struct nd_region *nd_region); #else static inline int nd_dax_probe(struct device *dev, @@ -608,7 +608,7 @@ static inline int nd_dax_probe(struct device *dev, return -ENODEV; } -static inline bool is_nd_dax(struct device *dev) +static inline bool is_nd_dax(const struct device *dev) { return false; } diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 83dbf398ea84..8f134d63af13 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -839,12 +839,12 @@ static const struct device_type nd_volatile_device_type = { .groups = nd_region_attribute_groups, }; -bool is_nd_pmem(struct device *dev) +bool is_nd_pmem(const struct device *dev) { return dev ? dev->type == &nd_pmem_device_type : false; } -bool is_nd_volatile(struct device *dev) +bool is_nd_volatile(const struct device *dev) { return dev ? dev->type == &nd_volatile_device_type : false; } diff --git a/drivers/of/device.c b/drivers/of/device.c index 8271793ef379..955bfb3d1a83 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -248,7 +248,7 @@ const void *of_device_get_match_data(const struct device *dev) } EXPORT_SYMBOL(of_device_get_match_data); -static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) +static ssize_t of_device_get_modalias(const struct device *dev, char *str, ssize_t len) { const char *compat; char *c; @@ -372,7 +372,7 @@ void of_device_uevent(const struct device *dev, struct kobj_uevent_env *env) mutex_unlock(&of_mutex); } -int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) +int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *env) { int sl; diff --git a/drivers/of/property.c b/drivers/of/property.c index 95b838185b2f..fb210e921ca9 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1062,20 +1062,6 @@ of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode, return of_device_get_match_data(dev); } -static bool of_is_ancestor_of(struct device_node *test_ancestor, - struct device_node *child) -{ - of_node_get(child); - while (child) { - if (child == test_ancestor) { - of_node_put(child); - return true; - } - child = of_get_next_parent(child); - } - return false; -} - static struct device_node *of_get_compat_node(struct device_node *np) { of_node_get(np); @@ -1106,71 +1092,27 @@ static struct device_node *of_get_compat_node_parent(struct device_node *np) return node; } -/** - * of_link_to_phandle - Add fwnode link to supplier from supplier phandle - * @con_np: consumer device tree node - * @sup_np: supplier device tree node - * - * Given a phandle to a supplier device tree node (@sup_np), this function - * finds the device that owns the supplier device tree node and creates a - * device link from @dev consumer device to the supplier device. This function - * doesn't create device links for invalid scenarios such as trying to create a - * link with a parent device as the consumer of its child device. In such - * cases, it returns an error. - * - * Returns: - * - 0 if fwnode link successfully created to supplier - * - -EINVAL if the supplier link is invalid and should not be created - * - -ENODEV if struct device will never be create for supplier - */ -static int of_link_to_phandle(struct device_node *con_np, +static void of_link_to_phandle(struct device_node *con_np, struct device_node *sup_np) { - struct device *sup_dev; - struct device_node *tmp_np = sup_np; + struct device_node *tmp_np = of_node_get(sup_np); - /* - * Find the device node that contains the supplier phandle. It may be - * @sup_np or it may be an ancestor of @sup_np. - */ - sup_np = of_get_compat_node(sup_np); - if (!sup_np) { - pr_debug("Not linking %pOFP to %pOFP - No device\n", - con_np, tmp_np); - return -ENODEV; - } + /* Check that sup_np and its ancestors are available. */ + while (tmp_np) { + if (of_fwnode_handle(tmp_np)->dev) { + of_node_put(tmp_np); + break; + } - /* - * Don't allow linking a device node as a consumer of one of its - * descendant nodes. By definition, a child node can't be a functional - * dependency for the parent node. - */ - if (of_is_ancestor_of(con_np, sup_np)) { - pr_debug("Not linking %pOFP to %pOFP - is descendant\n", - con_np, sup_np); - of_node_put(sup_np); - return -EINVAL; - } + if (!of_device_is_available(tmp_np)) { + of_node_put(tmp_np); + return; + } - /* - * Don't create links to "early devices" that won't have struct devices - * created for them. - */ - sup_dev = get_dev_from_fwnode(&sup_np->fwnode); - if (!sup_dev && - (of_node_check_flag(sup_np, OF_POPULATED) || - sup_np->fwnode.flags & FWNODE_FLAG_NOT_DEVICE)) { - pr_debug("Not linking %pOFP to %pOFP - No struct device\n", - con_np, sup_np); - of_node_put(sup_np); - return -ENODEV; + tmp_np = of_get_next_parent(tmp_np); } - put_device(sup_dev); fwnode_link_add(of_fwnode_handle(con_np), of_fwnode_handle(sup_np)); - of_node_put(sup_np); - - return 0; } /** diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index a2ceeacc33eb..d934c27491c4 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -1545,9 +1545,9 @@ void pci_dev_put(struct pci_dev *dev) } EXPORT_SYMBOL(pci_dev_put); -static int pci_uevent(struct device *dev, struct kobj_uevent_env *env) +static int pci_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct pci_dev *pdev; + const struct pci_dev *pdev; if (!dev) return -ENODEV; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index ace133b9f7d4..c8087efa5e4a 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -927,9 +927,9 @@ static int pcmcia_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int pcmcia_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct pcmcia_device *p_dev; + const struct pcmcia_device *p_dev; int i; u32 hash[4] = { 0, 0, 0, 0}; diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c index 7004eb4a63a2..aaad41294200 100644 --- a/drivers/platform/surface/aggregator/bus.c +++ b/drivers/platform/surface/aggregator/bus.c @@ -35,9 +35,9 @@ static struct attribute *ssam_device_attrs[] = { }; ATTRIBUTE_GROUPS(ssam_device); -static int ssam_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ssam_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct ssam_device *sdev = to_ssam_device(dev); + const struct ssam_device *sdev = to_ssam_device(dev); return add_uevent_var(env, "MODALIAS=ssam:d%02Xc%02Xt%02Xi%02Xf%02X", sdev->uid.domain, sdev->uid.category, diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 5ffc00480aef..4fe7650dd014 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -693,15 +693,8 @@ char *wmi_get_acpi_device_uid(const char *guid_string) } EXPORT_SYMBOL_GPL(wmi_get_acpi_device_uid); -static struct wmi_block *dev_to_wblock(struct device *dev) -{ - return container_of(dev, struct wmi_block, dev.dev); -} - -static struct wmi_device *dev_to_wdev(struct device *dev) -{ - return container_of(dev, struct wmi_device, dev); -} +#define dev_to_wblock(__dev) container_of_const(__dev, struct wmi_block, dev.dev) +#define dev_to_wdev(__dev) container_of_const(__dev, struct wmi_device, dev) static inline struct wmi_driver *drv_to_wdrv(struct device_driver *drv) { @@ -804,9 +797,9 @@ static struct attribute *wmi_method_attrs[] = { }; ATTRIBUTE_GROUPS(wmi_method); -static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +static int wmi_dev_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct wmi_block *wblock = dev_to_wblock(dev); + const struct wmi_block *wblock = dev_to_wblock(dev); if (add_uevent_var(env, "MODALIAS=wmi:%pUL", &wblock->gblock.guid)) return -ENOMEM; diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index a72bb0a40fcf..e60e49769bed 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -204,9 +204,9 @@ static int rio_match_bus(struct device *dev, struct device_driver *drv) out:return 0; } -static int rio_uevent(struct device *dev, struct kobj_uevent_env *env) +static int rio_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct rio_dev *rdev; + const struct rio_dev *rdev; if (!dev) return -ENODEV; diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index d6dde00efdae..a2207c0cf432 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -492,9 +492,9 @@ static int rpmsg_dev_match(struct device *dev, struct device_driver *drv) return of_driver_match_device(dev, drv); } -static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env) +static int rpmsg_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct rpmsg_device *rpdev = to_rpmsg_device(dev); + const struct rpmsg_device *rpdev = to_rpmsg_device(dev); int ret; ret = of_device_uevent_modalias(dev, env); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index dfbb998db86f..3ef636935a54 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1411,9 +1411,9 @@ static void css_shutdown(struct device *dev) sch->driver->shutdown(sch); } -static int css_uevent(struct device *dev, struct kobj_uevent_env *env) +static int css_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct subchannel *sch = to_subchannel(dev); + const struct subchannel *sch = to_subchannel(dev); int ret; ret = add_uevent_var(env, "ST=%01X", sch->st); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 5418e60dbfc3..8eb089b99cde 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -80,7 +80,7 @@ ccw_bus_match (struct device * dev, struct device_driver * drv) * specified size. Return length of resulting string (excluding trailing '\0') * even if string doesn't fit buffer (snprintf semantics). */ static int snprint_alias(char *buf, size_t size, - struct ccw_device_id *id, const char *suffix) + const struct ccw_device_id *id, const char *suffix) { int len; @@ -101,10 +101,10 @@ static int snprint_alias(char *buf, size_t size, /* Set up environment variables for ccw device uevent. Return 0 on success, * non-zero otherwise. */ -static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ccw_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct ccw_device *cdev = to_ccwdev(dev); - struct ccw_device_id *id = &(cdev->id); + const struct ccw_device *cdev = to_ccwdev(dev); + const struct ccw_device_id *id = &(cdev->id); int ret; char modalias_buf[30]; diff --git a/drivers/s390/cio/scm.c b/drivers/s390/cio/scm.c index b6b4589c70bd..6b21ba68c1fe 100644 --- a/drivers/s390/cio/scm.c +++ b/drivers/s390/cio/scm.c @@ -37,7 +37,7 @@ static void scmdev_remove(struct device *dev) scmdrv->remove(scmdev); } -static int scmdev_uevent(struct device *dev, struct kobj_uevent_env *env) +static int scmdev_uevent(const struct device *dev, struct kobj_uevent_env *env) { return add_uevent_var(env, "MODALIAS=scm:scmdev"); } diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index b02c631f3b71..f4cc1720156f 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -613,10 +613,10 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv) * It sets up a single environment variable DEV_TYPE which contains the * hardware device type. */ -static int ap_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ap_uevent(const struct device *dev, struct kobj_uevent_env *env) { int rc = 0; - struct ap_device *ap_dev = to_ap_dev(dev); + const struct ap_device *ap_dev = to_ap_dev(dev); /* Uevents from ap bus core don't need extensions to the env */ if (dev == ap_root_device) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 8ef9a5494340..ee28f73af4d4 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -536,9 +536,9 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } -static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int scsi_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct scsi_device *sdev; + const struct scsi_device *sdev; if (dev->type != &scsi_dev_type) return 0; diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index e24e220e56ee..e05473c5c267 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -760,12 +760,6 @@ static int maple_match_bus_driver(struct device *devptr, return 0; } -static int maple_bus_uevent(struct device *dev, - struct kobj_uevent_env *env) -{ - return 0; -} - static void maple_bus_release(struct device *dev) { } @@ -782,7 +776,6 @@ static struct maple_driver maple_unsupported_device = { struct bus_type maple_bus_type = { .name = "maple", .match = maple_match_bus_driver, - .uevent = maple_bus_uevent, }; EXPORT_SYMBOL_GPL(maple_bus_type); diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c index 219483b79c09..d43873bb5fe6 100644 --- a/drivers/slimbus/core.c +++ b/drivers/slimbus/core.c @@ -93,9 +93,9 @@ static void slim_device_remove(struct device *dev) } } -static int slim_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int slim_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct slim_device *sbdev = to_slim_device(dev); + const struct slim_device *sbdev = to_slim_device(dev); return add_uevent_var(env, "MODALIAS=slim:%s", dev_name(&sbdev->dev)); } diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 7a47d14fde44..4b3300b090a8 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -1518,7 +1518,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev) domain->genpd.power_off = imx_pgc_power_down; pd_pdev->dev.parent = dev; - pd_pdev->dev.of_node = np; + device_set_node(&pd_pdev->dev, of_fwnode_handle(np)); ret = platform_device_add(pd_pdev); if (ret) { diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index d51abb462ae5..30f81d6d9d9d 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -387,9 +387,9 @@ static void apr_device_remove(struct device *dev) spin_unlock(&apr->svcs_lock); } -static int apr_uevent(struct device *dev, struct kobj_uevent_env *env) +static int apr_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct apr_device *adev = to_apr_device(dev); + const struct apr_device *adev = to_apr_device(dev); int ret; ret = of_device_uevent_modalias(dev, env); diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index b0a80de34c98..eed47696e825 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -437,7 +437,7 @@ static int __init rcar_sysc_pd_init(void) error = of_genpd_add_provider_onecell(np, &domains->onecell_data); if (!error) - of_node_set_flag(np, OF_POPULATED); + fwnode_dev_initialized(of_fwnode_handle(np), true); out_put: of_node_put(np); diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index 04b3529f8929..26c9a0a85d49 100644 --- a/drivers/soundwire/bus_type.c +++ b/drivers/soundwire/bus_type.c @@ -58,9 +58,9 @@ int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size) slave->id.sdw_version, slave->id.class_id); } -int sdw_slave_uevent(struct device *dev, struct kobj_uevent_env *env) +int sdw_slave_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct sdw_slave *slave = dev_to_sdw_dev(dev); + const struct sdw_slave *slave = dev_to_sdw_dev(dev); char modalias[32]; sdw_slave_modalias(slave, modalias, sizeof(modalias)); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5866bf5813a4..44b85a8d47f1 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -395,7 +395,7 @@ static int spi_match_device(struct device *dev, struct device_driver *drv) return strcmp(spi->modalias, drv->name) == 0; } -static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) +static int spi_uevent(const struct device *dev, struct kobj_uevent_env *env) { const struct spi_device *spi = to_spi_device(dev); int rc; diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c index 55381592bb5a..73551531ed43 100644 --- a/drivers/spmi/spmi.c +++ b/drivers/spmi/spmi.c @@ -366,7 +366,7 @@ static void spmi_drv_shutdown(struct device *dev) sdrv->shutdown(to_spmi_device(dev)); } -static int spmi_drv_uevent(struct device *dev, struct kobj_uevent_env *env) +static int spmi_drv_uevent(const struct device *dev, struct kobj_uevent_env *env) { int ret; diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 8a93c83cb6f8..ab080cf26c9f 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -339,9 +339,9 @@ static int ssb_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int ssb_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ssb_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); + const struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); if (!dev) return -ENODEV; diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 0ad8aeabccbf..72ace74ea605 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -1075,11 +1075,6 @@ static int gbaudio_codec_probe(struct platform_device *pdev) gbaudio_dai, ARRAY_SIZE(gbaudio_dai)); } -static int gbaudio_codec_remove(struct platform_device *pdev) -{ - return 0; -} - static const struct of_device_id greybus_asoc_machine_of_match[] = { { .compatible = "toshiba,apb-dummy-codec", }, {}, @@ -1094,7 +1089,6 @@ static struct platform_driver gbaudio_codec_driver = { .of_match_table = greybus_asoc_machine_of_match, }, .probe = gbaudio_codec_probe, - .remove = gbaudio_codec_remove, }; module_platform_driver(gbaudio_codec_driver); diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c index 5a5c17a4519b..6a7d8cf2a1eb 100644 --- a/drivers/staging/greybus/gbphy.c +++ b/drivers/staging/greybus/gbphy.c @@ -71,14 +71,14 @@ static const struct device_type greybus_gbphy_dev_type = { .pm = &gb_gbphy_pm_ops, }; -static int gbphy_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +static int gbphy_dev_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); - struct greybus_descriptor_cport *cport_desc = gbphy_dev->cport_desc; - struct gb_bundle *bundle = gbphy_dev->bundle; - struct gb_interface *intf = bundle->intf; - struct gb_module *module = intf->module; - struct gb_host_device *hd = intf->hd; + const struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); + const struct greybus_descriptor_cport *cport_desc = gbphy_dev->cport_desc; + const struct gb_bundle *bundle = gbphy_dev->bundle; + const struct gb_interface *intf = bundle->intf; + const struct gb_module *module = intf->module; + const struct gb_host_device *hd = intf->hd; if (add_uevent_var(env, "BUS=%u", hd->bus_id)) return -ENOMEM; diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 98da206cd761..452cbb8ad484 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -1207,7 +1207,7 @@ static int tee_client_device_match(struct device *dev, return 0; } -static int tee_client_device_uevent(struct device *dev, +static int tee_client_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { uuid_t *dev_id = &to_tee_client_device(dev)->id.uuid; diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index e1ad1b437291..3370e18ba05f 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2184,9 +2184,9 @@ static void tb_switch_release(struct device *dev) kfree(sw); } -static int tb_switch_uevent(struct device *dev, struct kobj_uevent_env *env) +static int tb_switch_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct tb_switch *sw = tb_to_switch(dev); + const struct tb_switch *sw = tb_to_switch(dev); const char *type; if (sw->config.thunderbolt_version == USB4_VERSION_1_0) { diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 2953cf38c29e..cbb20a277346 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -837,7 +837,7 @@ static inline bool tb_is_switch(const struct device *dev) return dev->type == &tb_switch_type; } -static inline struct tb_switch *tb_to_switch(struct device *dev) +static inline struct tb_switch *tb_to_switch(const struct device *dev) { if (tb_is_switch(dev)) return container_of(dev, struct tb_switch, dev); diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c index 3c51e47dd86b..a48335c95d39 100644 --- a/drivers/thunderbolt/xdomain.c +++ b/drivers/thunderbolt/xdomain.c @@ -881,7 +881,7 @@ static ssize_t key_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(key); -static int get_modalias(struct tb_service *svc, char *buf, size_t size) +static int get_modalias(const struct tb_service *svc, char *buf, size_t size) { return snprintf(buf, size, "tbsvc:k%sp%08Xv%08Xr%08X", svc->key, svc->prtcid, svc->prtcvers, svc->prtcrevs); @@ -953,9 +953,9 @@ static const struct attribute_group *tb_service_attr_groups[] = { NULL, }; -static int tb_service_uevent(struct device *dev, struct kobj_uevent_env *env) +static int tb_service_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct tb_service *svc = container_of(dev, struct tb_service, dev); + const struct tb_service *svc = container_of_const(dev, struct tb_service, dev); char modalias[64]; get_modalias(svc, modalias, sizeof(modalias)); diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 0180e1e4e75d..aa80de3a8194 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -42,7 +42,7 @@ static struct attribute *serdev_device_attrs[] = { }; ATTRIBUTE_GROUPS(serdev_device); -static int serdev_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int serdev_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { int rc; diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 748e8b1cf4f7..59e25f2b6632 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -631,12 +631,6 @@ static int arc_serial_probe(struct platform_device *pdev) return uart_add_one_port(&arc_uart_driver, &arc_uart_ports[dev_id].port); } -static int arc_serial_remove(struct platform_device *pdev) -{ - /* This will never be called */ - return 0; -} - static const struct of_device_id arc_uart_dt_ids[] = { { .compatible = "snps,arc-uart" }, { /* Sentinel */ } @@ -645,7 +639,6 @@ MODULE_DEVICE_TABLE(of, arc_uart_dt_ids); static struct platform_driver arc_platform_driver = { .probe = arc_serial_probe, - .remove = arc_serial_remove, .driver = { .name = DRIVER_NAME, .of_match_table = arc_uart_dt_ids, diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 38703781ee2d..a98b2108376a 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -55,9 +55,9 @@ static int ulpi_match(struct device *dev, struct device_driver *driver) return 0; } -static int ulpi_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ulpi_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct ulpi *ulpi = to_ulpi_dev(dev); + const struct ulpi *ulpi = to_ulpi_dev(dev); int ret; ret = of_device_uevent_modalias(dev, env); diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 7e7e119c253f..a0e076c6f3a4 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -899,14 +899,14 @@ static int usb_device_match(struct device *dev, struct device_driver *drv) return 0; } -static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) +static int usb_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct usb_device *usb_dev; + const struct usb_device *usb_dev; if (is_usb_device(dev)) { usb_dev = to_usb_device(dev); } else if (is_usb_interface(dev)) { - struct usb_interface *intf = to_usb_interface(dev); + const struct usb_interface *intf = to_usb_interface(dev); usb_dev = interface_to_usbdev(intf); } else { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 127fac1af676..cc404bb7e8f7 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1819,11 +1819,11 @@ void usb_authorize_interface(struct usb_interface *intf) } } -static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) +static int usb_if_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct usb_device *usb_dev; - struct usb_interface *intf; - struct usb_host_interface *alt; + const struct usb_device *usb_dev; + const struct usb_interface *intf; + const struct usb_host_interface *alt; intf = to_usb_interface(dev); usb_dev = interface_to_usbdev(intf); diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index a415206cab04..34742fbbd84d 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -423,9 +423,9 @@ static void usb_release_dev(struct device *dev) kfree(udev); } -static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +static int usb_dev_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct usb_device *usb_dev; + const struct usb_device *usb_dev; usb_dev = to_usb_device(dev); @@ -505,10 +505,10 @@ static const struct dev_pm_ops usb_device_pm_ops = { #endif /* CONFIG_PM */ -static char *usb_devnode(struct device *dev, +static char *usb_devnode(const struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid) { - struct usb_device *usb_dev; + const struct usb_device *usb_dev; usb_dev = to_usb_device(dev); return kasprintf(GFP_KERNEL, "bus/usb/%03d/%03d", diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index 1b24492bb4e5..4b468bde19cf 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -80,7 +80,7 @@ static struct usb_phy *__of_usb_find_phy(struct device_node *node) return ERR_PTR(-EPROBE_DEFER); } -static struct usb_phy *__device_to_usb_phy(struct device *dev) +static struct usb_phy *__device_to_usb_phy(const struct device *dev) { struct usb_phy *usb_phy; @@ -145,9 +145,9 @@ static void usb_phy_notify_charger_work(struct work_struct *work) kobject_uevent(&usb_phy->dev->kobj, KOBJ_CHANGE); } -static int usb_phy_uevent(struct device *dev, struct kobj_uevent_env *env) +static int usb_phy_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct usb_phy *usb_phy; + const struct usb_phy *usb_phy; char uchger_state[50] = { 0 }; char uchger_type[50] = { 0 }; unsigned long flags; diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index eacb46ec2ab3..56814ef80c24 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -274,8 +274,7 @@ static const struct attribute_group *usb_role_switch_groups[] = { NULL, }; -static int -usb_role_switch_uevent(struct device *dev, struct kobj_uevent_env *env) +static int usb_role_switch_uevent(const struct device *dev, struct kobj_uevent_env *env) { int ret; diff --git a/drivers/usb/typec/bus.c b/drivers/usb/typec/bus.c index 0c8d554240be..098f0efaa58d 100644 --- a/drivers/usb/typec/bus.c +++ b/drivers/usb/typec/bus.c @@ -350,9 +350,9 @@ static int typec_match(struct device *dev, struct device_driver *driver) return 0; } -static int typec_uevent(struct device *dev, struct kobj_uevent_env *env) +static int typec_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct typec_altmode *altmode = to_typec_altmode(dev); + const struct typec_altmode *altmode = to_typec_altmode(dev); if (add_uevent_var(env, "SVID=%04X", altmode->svid)) return -ENOMEM; diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index ed3d070b1ca4..cc3182f70673 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -1738,7 +1738,7 @@ static const struct attribute_group *typec_groups[] = { NULL }; -static int typec_uevent(struct device *dev, struct kobj_uevent_env *env) +static int typec_uevent(const struct device *dev, struct kobj_uevent_env *env) { int ret; diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index b9a80aedee1b..3893dc29eb26 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -95,9 +95,9 @@ static int virtio_dev_match(struct device *_dv, struct device_driver *_dr) return 0; } -static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) +static int virtio_uevent(const struct device *_dv, struct kobj_uevent_env *env) { - struct virtio_device *dev = dev_to_virtio(_dv); + const struct virtio_device *dev = dev_to_virtio(_dv); return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X", dev->id.device, dev->id.vendor); diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 4a2ddf730a3a..9d199fed9628 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -170,7 +170,7 @@ static struct w1_family w1_default_family = { .fops = &w1_default_fops, }; -static int w1_uevent(struct device *dev, struct kobj_uevent_env *env); +static int w1_uevent(const struct device *dev, struct kobj_uevent_env *env); static struct bus_type w1_bus_type = { .name = "w1", @@ -577,11 +577,11 @@ void w1_destroy_master_attributes(struct w1_master *master) sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group); } -static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) +static int w1_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct w1_master *md = NULL; - struct w1_slave *sl = NULL; - char *event_owner, *name; + const struct w1_master *md = NULL; + const struct w1_slave *sl = NULL; + const char *event_owner, *name; int err = 0; if (dev->driver == &w1_master_driver) { diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c index dcb00938de61..1f5219e12cc3 100644 --- a/drivers/xen/pvcalls-back.c +++ b/drivers/xen/pvcalls-back.c @@ -1191,7 +1191,7 @@ static void pvcalls_back_remove(struct xenbus_device *dev) { } -static int pvcalls_back_uevent(struct xenbus_device *xdev, +static int pvcalls_back_uevent(const struct xenbus_device *xdev, struct kobj_uevent_env *env) { return 0; diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c index 9c09f89d8278..da96c260e26b 100644 --- a/drivers/xen/xenbus/xenbus_probe_backend.c +++ b/drivers/xen/xenbus/xenbus_probe_backend.c @@ -92,12 +92,12 @@ static int backend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) return 0; } -static int xenbus_uevent_backend(struct device *dev, +static int xenbus_uevent_backend(const struct device *dev, struct kobj_uevent_env *env) { - struct xenbus_device *xdev; - struct xenbus_driver *drv; - struct xen_bus_type *bus; + const struct xenbus_device *xdev; + const struct xenbus_driver *drv; + const struct xen_bus_type *bus; DPRINTK(""); diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index f44d5a64351e..3f3836cb7279 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -73,10 +73,10 @@ static int xenbus_probe_frontend(struct xen_bus_type *bus, const char *type, return err; } -static int xenbus_uevent_frontend(struct device *_dev, +static int xenbus_uevent_frontend(const struct device *_dev, struct kobj_uevent_env *env) { - struct xenbus_device *dev = to_xenbus_device(_dev); + const struct xenbus_device *dev = to_xenbus_device(_dev); if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype)) return -ENOMEM; diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index 96f068830549..025edfccedcf 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -130,9 +130,9 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv) return !!zorro_match_device(ids, z); } -static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) +static int zorro_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct zorro_dev *z; + const struct zorro_dev *z; if (!dev) return -ENODEV; diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index bf397f6a6a33..3f81f73c241a 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -802,8 +802,8 @@ EXPORT_SYMBOL_GPL(debugfs_lookup_and_remove); * exist for rename to succeed. * * This function will return a pointer to old_dentry (which is updated to - * reflect renaming) if it succeeds. If an error occurs, %NULL will be - * returned. + * reflect renaming) if it succeeds. If an error occurs, ERR_PTR(-ERROR) + * will be returned. * * If debugfs is not enabled in the kernel, the value -%ENODEV will be * returned. diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 9f344d76afa3..7325acbd1af7 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -215,9 +215,9 @@ static int do_uevent(struct dlm_ls *ls, int in) return ls->ls_uevent_result; } -static int dlm_uevent(struct kobject *kobj, struct kobj_uevent_env *env) +static int dlm_uevent(const struct kobject *kobj, struct kobj_uevent_env *env) { - struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj); + const struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj); add_uevent_var(env, "LOCKSPACE=%s", ls->ls_name); return 0; diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index c40118ea4bbc..454dc2ff8b5e 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -769,10 +769,10 @@ void gfs2_sys_fs_del(struct gfs2_sbd *sdp) wait_for_completion(&sdp->sd_kobj_unregister); } -static int gfs2_uevent(struct kobject *kobj, struct kobj_uevent_env *env) +static int gfs2_uevent(const struct kobject *kobj, struct kobj_uevent_env *env) { - struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); - struct super_block *s = sdp->sd_vfs; + const struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); + const struct super_block *s = sdp->sd_vfs; add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name); add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index e3181c3e1988..ef00b5fe8cee 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -149,9 +149,6 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, if (kn_from == kn_to) return strlcpy(buf, "/", buflen); - if (!buf) - return -EINVAL; - common = kernfs_common_ancestor(kn_from, kn_to); if (WARN_ON(!common)) return -EINVAL; diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h index c13f46109e88..46a0016efd81 100644 --- a/include/asm-generic/dma-mapping.h +++ b/include/asm-generic/dma-mapping.h @@ -2,7 +2,7 @@ #ifndef _ASM_GENERIC_DMA_MAPPING_H #define _ASM_GENERIC_DMA_MAPPING_H -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) +static inline const struct dma_map_ops *get_arch_dma_ops(void) { return NULL; } diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 16f30975b22b..c9df0407980c 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -197,10 +197,7 @@ struct mipi_dsi_device { #define MIPI_DSI_MODULE_PREFIX "mipi-dsi:" -static inline struct mipi_dsi_device *to_mipi_dsi_device(struct device *dev) -{ - return container_of(dev, struct mipi_dsi_device, dev); -} +#define to_mipi_dsi_device(__dev) container_of_const(__dev, struct mipi_dsi_device, dev) /** * mipi_dsi_pixel_format_to_bpp - obtain the number of bits per pixel for any diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4b12dad5a8a4..efff750f326d 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -723,7 +723,7 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, const void *acpi_device_get_match_data(const struct device *dev); extern bool acpi_driver_match_device(struct device *dev, const struct device_driver *drv); -int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *); +int acpi_device_uevent_modalias(const struct device *, struct kobj_uevent_env *); int acpi_device_modalias(struct device *, char *, int); struct platform_device *acpi_create_platform_device(struct acpi_device *, @@ -973,7 +973,7 @@ static inline union acpi_object *acpi_evaluate_dsm_typed(acpi_handle handle, return NULL; } -static inline int acpi_device_uevent_modalias(struct device *dev, +static inline int acpi_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 00b7a6ae8617..908e19d17f49 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -80,26 +80,31 @@ struct cpu_cacheinfo { struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu); int init_cache_level(unsigned int cpu); +int init_of_cache_level(unsigned int cpu); int populate_cache_leaves(unsigned int cpu); int cache_setup_acpi(unsigned int cpu); bool last_level_cache_is_valid(unsigned int cpu); bool last_level_cache_is_shared(unsigned int cpu_x, unsigned int cpu_y); +int fetch_cache_info(unsigned int cpu); int detect_cache_attributes(unsigned int cpu); #ifndef CONFIG_ACPI_PPTT /* - * acpi_find_last_cache_level is only called on ACPI enabled + * acpi_get_cache_info() is only called on ACPI enabled * platforms using the PPTT for topology. This means that if * the platform supports other firmware configuration methods * we need to stub out the call when ACPI is disabled. * ACPI enabled platforms not using PPTT won't be making calls * to this function so we need not worry about them. */ -static inline int acpi_find_last_cache_level(unsigned int cpu) +static inline +int acpi_get_cache_info(unsigned int cpu, + unsigned int *levels, unsigned int *split_levels) { - return 0; + return -ENOENT; } #else -int acpi_find_last_cache_level(unsigned int cpu); +int acpi_get_cache_info(unsigned int cpu, + unsigned int *levels, unsigned int *split_levels); #endif const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf); diff --git a/include/linux/container_of.h b/include/linux/container_of.h index 1d898f9158b4..713890c867be 100644 --- a/include/linux/container_of.h +++ b/include/linux/container_of.h @@ -3,7 +3,7 @@ #define _LINUX_CONTAINER_OF_H #include <linux/build_bug.h> -#include <linux/err.h> +#include <linux/stddef.h> #define typeof_member(T, m) typeof(((T*)0)->m) diff --git a/include/linux/device.h b/include/linux/device.h index 44e3acae7b36..1508e637bb26 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -88,8 +88,8 @@ int subsys_virtual_register(struct bus_type *subsys, struct device_type { const char *name; const struct attribute_group **groups; - int (*uevent)(struct device *dev, struct kobj_uevent_env *env); - char *(*devnode)(struct device *dev, umode_t *mode, + int (*uevent)(const struct device *dev, struct kobj_uevent_env *env); + char *(*devnode)(const struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid); void (*release)(struct device *dev); @@ -328,6 +328,7 @@ enum device_link_state { #define DL_FLAG_MANAGED BIT(6) #define DL_FLAG_SYNC_STATE_ONLY BIT(7) #define DL_FLAG_INFERRED BIT(8) +#define DL_FLAG_CYCLE BIT(9) /** * enum dl_dev_state - Device driver presence tracking information. @@ -907,8 +908,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); -const char *device_get_devnode(struct device *dev, umode_t *mode, kuid_t *uid, - kgid_t *gid, const char **tmp); 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 d8b29ccd07e5..6ce32ef4b8fd 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -66,8 +66,6 @@ struct fwnode_handle; * @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU * driver implementations to a bus and allow the driver to do * bus-specific setup - * @p: The private data of the driver core, only the driver core can - * touch this. * @lock_key: Lock class key for use by the lock validator * @need_parent_lock: When probing or removing a device on this bus, the * device core should lock the device's parent. @@ -90,7 +88,7 @@ struct bus_type { const struct attribute_group **drv_groups; int (*match)(struct device *dev, struct device_driver *drv); - int (*uevent)(struct device *dev, struct kobj_uevent_env *env); + int (*uevent)(const struct device *dev, struct kobj_uevent_env *env); int (*probe)(struct device *dev); void (*sync_state)(struct device *dev); void (*remove)(struct device *dev); @@ -111,15 +109,12 @@ struct bus_type { const struct iommu_ops *iommu_ops; - struct subsys_private *p; - struct lock_class_key lock_key; - bool need_parent_lock; }; extern int __must_check bus_register(struct bus_type *bus); -extern void bus_unregister(struct bus_type *bus); +extern void bus_unregister(const struct bus_type *bus); extern int __must_check bus_rescan_devices(struct bus_type *bus); @@ -136,9 +131,8 @@ struct bus_attribute { #define BUS_ATTR_WO(_name) \ struct bus_attribute bus_attr_##_name = __ATTR_WO(_name) -extern int __must_check bus_create_file(struct bus_type *, - struct bus_attribute *); -extern void bus_remove_file(struct bus_type *, struct bus_attribute *); +int __must_check bus_create_file(const struct bus_type *bus, struct bus_attribute *attr); +void bus_remove_file(const struct bus_type *bus, struct bus_attribute *attr); /* Generic device matching functions that all busses can use to match with */ int device_match_name(struct device *dev, const void *name); @@ -150,20 +144,9 @@ int device_match_acpi_handle(struct device *dev, const void *handle); int device_match_any(struct device *dev, const void *unused); /* iterator helpers for buses */ -struct subsys_dev_iter { - struct klist_iter ki; - const struct device_type *type; -}; -void subsys_dev_iter_init(struct subsys_dev_iter *iter, - struct bus_type *subsys, - struct device *start, - const struct device_type *type); -struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter); -void subsys_dev_iter_exit(struct subsys_dev_iter *iter); - -int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, +int bus_for_each_dev(const struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); -struct device *bus_find_device(struct bus_type *bus, struct device *start, +struct device *bus_find_device(const struct bus_type *bus, struct device *start, const void *data, int (*match)(struct device *dev, const void *data)); /** @@ -173,7 +156,7 @@ struct device *bus_find_device(struct bus_type *bus, struct device *start, * @start: Device to begin with * @name: name of the device to match */ -static inline struct device *bus_find_device_by_name(struct bus_type *bus, +static inline struct device *bus_find_device_by_name(const struct bus_type *bus, struct device *start, const char *name) { @@ -187,7 +170,7 @@ static inline struct device *bus_find_device_by_name(struct bus_type *bus, * @np: of_node of the device to match. */ static inline struct device * -bus_find_device_by_of_node(struct bus_type *bus, const struct device_node *np) +bus_find_device_by_of_node(const struct bus_type *bus, const struct device_node *np) { return bus_find_device(bus, NULL, np, device_match_of_node); } @@ -199,7 +182,7 @@ bus_find_device_by_of_node(struct bus_type *bus, const struct device_node *np) * @fwnode: fwnode of the device to match. */ static inline struct device * -bus_find_device_by_fwnode(struct bus_type *bus, const struct fwnode_handle *fwnode) +bus_find_device_by_fwnode(const struct bus_type *bus, const struct fwnode_handle *fwnode) { return bus_find_device(bus, NULL, fwnode, device_match_fwnode); } @@ -210,7 +193,7 @@ bus_find_device_by_fwnode(struct bus_type *bus, const struct fwnode_handle *fwno * @bus: bus type * @devt: device type of the device to match. */ -static inline struct device *bus_find_device_by_devt(struct bus_type *bus, +static inline struct device *bus_find_device_by_devt(const struct bus_type *bus, dev_t devt) { return bus_find_device(bus, NULL, &devt, device_match_devt); @@ -223,7 +206,7 @@ static inline struct device *bus_find_device_by_devt(struct bus_type *bus, * @cur: device to begin the search with. */ static inline struct device * -bus_find_next_device(struct bus_type *bus,struct device *cur) +bus_find_next_device(const struct bus_type *bus,struct device *cur) { return bus_find_device(bus, cur, NULL, device_match_any); } @@ -238,21 +221,19 @@ struct acpi_device; * @adev: ACPI COMPANION device to match. */ static inline struct device * -bus_find_device_by_acpi_dev(struct bus_type *bus, const struct acpi_device *adev) +bus_find_device_by_acpi_dev(const struct bus_type *bus, const struct acpi_device *adev) { return bus_find_device(bus, NULL, adev, device_match_acpi_dev); } #else static inline struct device * -bus_find_device_by_acpi_dev(struct bus_type *bus, const void *adev) +bus_find_device_by_acpi_dev(const struct bus_type *bus, const void *adev) { return NULL; } #endif -struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id, - struct device *hint); -int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, +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, int (*compare)(const struct device *a, @@ -265,28 +246,42 @@ void bus_sort_breadthfirst(struct bus_type *bus, */ struct notifier_block; -extern int bus_register_notifier(struct bus_type *bus, +extern int bus_register_notifier(const struct bus_type *bus, struct notifier_block *nb); -extern int bus_unregister_notifier(struct bus_type *bus, +extern int bus_unregister_notifier(const struct bus_type *bus, struct notifier_block *nb); -/* All 4 notifers below get called with the target struct device * - * as an argument. Note that those functions are likely to be called - * with the device lock held in the core, so be careful. +/** + * enum bus_notifier_event - Bus Notifier events that have happened + * @BUS_NOTIFY_ADD_DEVICE: device is added to this bus + * @BUS_NOTIFY_DEL_DEVICE: device is about to be removed from this bus + * @BUS_NOTIFY_REMOVED_DEVICE: device is successfully removed from this bus + * @BUS_NOTIFY_BIND_DRIVER: a driver is about to be bound to this device on this bus + * @BUS_NOTIFY_BOUND_DRIVER: a driver is successfully bound to this device on this bus + * @BUS_NOTIFY_UNBIND_DRIVER: a driver is about to be unbound from this device on this bus + * @BUS_NOTIFY_UNBOUND_DRIVER: a driver is successfully unbound from this device on this bus + * @BUS_NOTIFY_DRIVER_NOT_BOUND: a driver failed to be bound to this device on this bus + * + * These are the value passed to a bus notifier when a specific event happens. + * + * Note that bus notifiers are likely to be called with the device lock already + * held by the driver core, so be careful in any notifier callback as to what + * you do with the device structure. + * + * All bus notifiers are called with the target struct device * as an argument. */ -#define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ -#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device to be removed */ -#define BUS_NOTIFY_REMOVED_DEVICE 0x00000003 /* device removed */ -#define BUS_NOTIFY_BIND_DRIVER 0x00000004 /* driver about to be - bound */ -#define BUS_NOTIFY_BOUND_DRIVER 0x00000005 /* driver bound to device */ -#define BUS_NOTIFY_UNBIND_DRIVER 0x00000006 /* driver about to be - unbound */ -#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000007 /* driver is unbound - from the device */ -#define BUS_NOTIFY_DRIVER_NOT_BOUND 0x00000008 /* driver fails to be bound */ +enum bus_notifier_event { + BUS_NOTIFY_ADD_DEVICE, + BUS_NOTIFY_DEL_DEVICE, + BUS_NOTIFY_REMOVED_DEVICE, + BUS_NOTIFY_BIND_DRIVER, + BUS_NOTIFY_BOUND_DRIVER, + BUS_NOTIFY_UNBIND_DRIVER, + BUS_NOTIFY_UNBOUND_DRIVER, + BUS_NOTIFY_DRIVER_NOT_BOUND, +}; -extern struct kset *bus_get_kset(struct bus_type *bus); -extern struct klist *bus_get_device_klist(struct bus_type *bus); +extern struct kset *bus_get_kset(const struct bus_type *bus); +struct device *bus_get_dev_root(const struct bus_type *bus); #endif diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index 2114d65b862f..50d0a416a5e7 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -240,7 +240,6 @@ driver_find_device_by_acpi_dev(struct device_driver *drv, const void *adev) } #endif -extern int driver_deferred_probe_timeout; void driver_deferred_probe_add(struct device *dev); int driver_deferred_probe_check_state(struct device *dev); void driver_init(void); diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h index d678afeb8a13..41bf4bdb117a 100644 --- a/include/linux/dma-map-ops.h +++ b/include/linux/dma-map-ops.h @@ -90,7 +90,7 @@ static inline const struct dma_map_ops *get_dma_ops(struct device *dev) { if (dev->dma_ops) return dev->dma_ops; - return get_arch_dma_ops(dev->bus); + return get_arch_dma_ops(); } static inline void set_dma_ops(struct device *dev, diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 56505436d159..1716c01c4e54 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -208,10 +208,7 @@ struct fw_device { struct fw_attribute_group attribute_group; }; -static inline struct fw_device *fw_device(struct device *dev) -{ - return container_of(dev, struct fw_device, device); -} +#define fw_device(dev) container_of_const(dev, struct fw_device, device) static inline int fw_device_is_shutdown(struct fw_device *device) { @@ -229,10 +226,7 @@ struct fw_unit { struct fw_attribute_group attribute_group; }; -static inline struct fw_unit *fw_unit(struct device *dev) -{ - return container_of(dev, struct fw_unit, device); -} +#define fw_unit(dev) container_of_const(dev, struct fw_unit, device) static inline struct fw_unit *fw_unit_get(struct fw_unit *unit) { @@ -246,10 +240,7 @@ static inline void fw_unit_put(struct fw_unit *unit) put_device(&unit->device); } -static inline struct fw_device *fw_parent_device(struct fw_unit *unit) -{ - return fw_device(unit->device.parent); -} +#define fw_parent_device(unit) fw_device(unit->device.parent) struct ieee1394_device_id; diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 89b9bdfca925..5700451b300f 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -18,7 +18,7 @@ struct fwnode_operations; struct device; /* - * fwnode link flags + * fwnode flags * * LINKS_ADDED: The fwnode has already be parsed to add fwnode links. * NOT_DEVICE: The fwnode will never be populated as a struct device. @@ -36,6 +36,7 @@ struct device; #define FWNODE_FLAG_INITIALIZED BIT(2) #define FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD BIT(3) #define FWNODE_FLAG_BEST_EFFORT BIT(4) +#define FWNODE_FLAG_VISITED BIT(5) struct fwnode_handle { struct fwnode_handle *secondary; @@ -46,11 +47,19 @@ struct fwnode_handle { u8 flags; }; +/* + * fwnode link flags + * + * CYCLE: The fwnode link is part of a cycle. Don't defer probe. + */ +#define FWLINK_FLAG_CYCLE BIT(0) + struct fwnode_link { struct fwnode_handle *supplier; struct list_head s_hook; struct fwnode_handle *consumer; struct list_head c_hook; + u8 flags; }; /** @@ -198,7 +207,6 @@ static inline void fwnode_dev_initialized(struct fwnode_handle *fwnode, fwnode->flags &= ~FWNODE_FLAG_INITIALIZED; } -extern u32 fw_devlink_get_flags(void); extern bool fw_devlink_is_strict(void); int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup); void fwnode_links_purge(struct fwnode_handle *fwnode); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index cd5cb9f6fae0..bfbc37ce223b 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1309,10 +1309,7 @@ struct hv_device { }; -static inline struct hv_device *device_to_hv_device(struct device *d) -{ - return container_of(d, struct hv_device, device); -} +#define device_to_hv_device(d) container_of_const(d, struct hv_device, device) static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d) { diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h index 1c997abe868c..90fa83464f00 100644 --- a/include/linux/i3c/device.h +++ b/include/linux/i3c/device.h @@ -18,17 +18,18 @@ /** * enum i3c_error_code - I3C error codes * + * @I3C_ERROR_UNKNOWN: unknown error, usually means the error is not I3C + * related + * @I3C_ERROR_M0: M0 error + * @I3C_ERROR_M1: M1 error + * @I3C_ERROR_M2: M2 error + * * These are the standard error codes as defined by the I3C specification. * When -EIO is returned by the i3c_device_do_priv_xfers() or * i3c_device_send_hdr_cmds() one can check the error code in * &struct_i3c_priv_xfer.err or &struct i3c_hdr_cmd.err to get a better idea of * what went wrong. * - * @I3C_ERROR_UNKNOWN: unknown error, usually means the error is not I3C - * related - * @I3C_ERROR_M0: M0 error - * @I3C_ERROR_M1: M1 error - * @I3C_ERROR_M2: M2 error */ enum i3c_error_code { I3C_ERROR_UNKNOWN = 0, @@ -186,7 +187,14 @@ static inline struct i3c_driver *drv_to_i3cdrv(struct device_driver *drv) } struct device *i3cdev_to_dev(struct i3c_device *i3cdev); -struct i3c_device *dev_to_i3cdev(struct device *dev); + +/** + * dev_to_i3cdev() - Returns the I3C device containing @dev + * @__dev: device object + * + * Return: a pointer to an I3C device object. + */ +#define dev_to_i3cdev(__dev) container_of_const(__dev, struct i3c_device, dev) const struct i3c_device_id * i3c_device_match_id(struct i3c_device *i3cdev, @@ -296,7 +304,7 @@ int i3c_device_do_priv_xfers(struct i3c_device *dev, int i3c_device_do_setdasa(struct i3c_device *dev); -void i3c_device_get_info(struct i3c_device *dev, struct i3c_device_info *info); +void i3c_device_get_info(const struct i3c_device *dev, struct i3c_device_info *info); struct i3c_ibi_payload { unsigned int len; diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 58a5b75612e3..bdab370a24f4 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -137,7 +137,7 @@ struct kobj_uevent_env { struct kset_uevent_ops { int (* const filter)(const struct kobject *kobj); const char *(* const name)(const struct kobject *kobj); - int (* const uevent)(struct kobject *kobj, struct kobj_uevent_env *env); + int (* const uevent)(const struct kobject *kobj, struct kobj_uevent_env *env); }; struct kobj_attribute { diff --git a/include/linux/mcb.h b/include/linux/mcb.h index f6efb16f9d1b..1e5893138afe 100644 --- a/include/linux/mcb.h +++ b/include/linux/mcb.h @@ -76,10 +76,7 @@ struct mcb_device { struct device *dma_dev; }; -static inline struct mcb_device *to_mcb_device(struct device *dev) -{ - return container_of(dev, struct mcb_device, dev); -} +#define to_mcb_device(__dev) container_of_const(__dev, struct mcb_device, dev) /** * struct mcb_driver - MEN Chameleon Bus device driver diff --git a/include/linux/of_device.h b/include/linux/of_device.h index ab7d557d541d..f4b57614979d 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -36,7 +36,7 @@ extern ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len); extern int of_device_request_module(struct device *dev); extern void of_device_uevent(const struct device *dev, struct kobj_uevent_env *env); -extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env); +extern int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *env); static inline struct device_node *of_cpu_device_node_get(int cpu) { @@ -83,7 +83,7 @@ static inline int of_device_request_module(struct device *dev) return -ENODEV; } -static inline int of_device_uevent_modalias(struct device *dev, +static inline int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index b0d5a253156e..b845fd83f429 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -207,7 +207,18 @@ extern void platform_device_put(struct platform_device *pdev); struct platform_driver { int (*probe)(struct platform_device *); + + /* + * Traditionally the remove callback returned an int which however is + * ignored by the driver core. This led to wrong expectations by driver + * authors who thought returning an error code was a valid error + * handling strategy. To convert to a callback returning void, new + * drivers should implement .remove_new() until the conversion it done + * that eventually makes .remove() return void. + */ int (*remove)(struct platform_device *); + void (*remove_new)(struct platform_device *); + void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t state); int (*resume)(struct platform_device *); diff --git a/include/linux/property.h b/include/linux/property.h index 37179e3abad5..0a29db15ff34 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -436,9 +436,9 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode, unsigned int fwnode_graph_get_endpoint_count(struct fwnode_handle *fwnode, unsigned long flags); -#define fwnode_graph_for_each_endpoint(fwnode, child) \ - for (child = NULL; \ - (child = fwnode_graph_get_next_endpoint(fwnode, child)); ) +#define fwnode_graph_for_each_endpoint(fwnode, child) \ + for (child = fwnode_graph_get_next_endpoint(fwnode, NULL); child; \ + child = fwnode_graph_get_next_endpoint(fwnode, child)) int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, struct fwnode_endpoint *endpoint); @@ -486,9 +486,6 @@ const struct software_node * software_node_find_by_name(const struct software_node *parent, const char *name); -int software_node_register_nodes(const struct software_node *nodes); -void software_node_unregister_nodes(const struct software_node *nodes); - int software_node_register_node_group(const struct software_node **node_group); void software_node_unregister_node_group(const struct software_node **node_group); diff --git a/include/linux/soundwire/sdw_type.h b/include/linux/soundwire/sdw_type.h index 52eb66cd11bc..d8c27f1e5559 100644 --- a/include/linux/soundwire/sdw_type.h +++ b/include/linux/soundwire/sdw_type.h @@ -21,7 +21,7 @@ static inline int is_sdw_slave(const struct device *dev) int __sdw_register_driver(struct sdw_driver *drv, struct module *owner); void sdw_unregister_driver(struct sdw_driver *drv); -int sdw_slave_uevent(struct device *dev, struct kobj_uevent_env *env); +int sdw_slave_uevent(const struct device *dev, struct kobj_uevent_env *env); /** * module_sdw_driver() - Helper macro for registering a Soundwire driver diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index a08c20bd833b..4fa26b9a3572 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -226,7 +226,7 @@ struct spi_device { static_assert((SPI_MODE_KERNEL_MASK & SPI_MODE_USER_MASK) == 0, "SPI_MODE_USER_MASK & SPI_MODE_KERNEL_MASK must not overlap"); -static inline struct spi_device *to_spi_device(struct device *dev) +static inline struct spi_device *to_spi_device(const struct device *dev) { return dev ? container_of(dev, struct spi_device, dev) : NULL; } diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index f9b53acb4e02..1f326da289d3 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -285,7 +285,7 @@ struct ssb_device { /* Go from struct device to struct ssb_device. */ static inline -struct ssb_device * dev_to_ssb_dev(struct device *dev) +struct ssb_device * dev_to_ssb_dev(const struct device *dev) { struct __ssb_dev_wrapper *wrap; wrap = container_of(dev, struct __ssb_dev_wrapper, dev); diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h index 1545e5567b15..df81043b9e71 100644 --- a/include/linux/surface_aggregator/device.h +++ b/include/linux/surface_aggregator/device.h @@ -229,10 +229,7 @@ static inline bool is_ssam_device(struct device *d) * Return: Returns a pointer to the &struct ssam_device wrapping the given * device @d. */ -static inline struct ssam_device *to_ssam_device(struct device *d) -{ - return container_of(d, struct ssam_device, dev); -} +#define to_ssam_device(d) container_of_const(d, struct ssam_device, dev) /** * to_ssam_device_driver() - Casts the given device driver to a SSAM client diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h index 63076fb835e3..2efc271a96fa 100644 --- a/include/linux/transport_class.h +++ b/include/linux/transport_class.h @@ -70,8 +70,14 @@ void transport_destroy_device(struct device *); static inline int transport_register_device(struct device *dev) { + int ret; + transport_setup_device(dev); - return transport_add_device(dev); + ret = transport_add_device(dev); + if (ret) + transport_destroy_device(dev); + + return ret; } static inline void diff --git a/include/linux/virtio.h b/include/linux/virtio.h index dcab9c7e8784..2b472514c49b 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -127,10 +127,7 @@ struct virtio_device { void *priv; }; -static inline struct virtio_device *dev_to_virtio(struct device *_dev) -{ - return container_of(_dev, struct virtio_device, dev); -} +#define dev_to_virtio(_dev) container_of_const(_dev, struct virtio_device, dev) void virtio_add_status(struct virtio_device *dev, unsigned int status); int register_virtio_device(struct virtio_device *dev); diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 536612c6ab0c..97f09acae302 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -123,7 +123,7 @@ void snd_hdac_device_exit(struct hdac_device *dev); int snd_hdac_device_register(struct hdac_device *codec); void snd_hdac_device_unregister(struct hdac_device *codec); int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name); -int snd_hdac_codec_modalias(struct hdac_device *hdac, char *buf, size_t size); +int snd_hdac_codec_modalias(const struct hdac_device *hdac, char *buf, size_t size); int snd_hdac_refresh_widgets(struct hdac_device *codec); diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h index ad4fb4eab753..ac22cf08c09f 100644 --- a/include/xen/xenbus.h +++ b/include/xen/xenbus.h @@ -96,10 +96,7 @@ struct xenbus_device { unsigned int spurious_threshold; }; -static inline struct xenbus_device *to_xenbus_device(struct device *dev) -{ - return container_of(dev, struct xenbus_device, dev); -} +#define to_xenbus_device(__dev) container_of_const(__dev, struct xenbus_device, dev) struct xenbus_device_id { @@ -120,7 +117,7 @@ struct xenbus_driver { void (*remove)(struct xenbus_device *dev); int (*suspend)(struct xenbus_device *dev); int (*resume)(struct xenbus_device *dev); - int (*uevent)(struct xenbus_device *, struct kobj_uevent_env *); + int (*uevent)(const struct xenbus_device *, struct kobj_uevent_env *); struct device_driver driver; int (*read_otherend_details)(struct xenbus_device *dev); int (*is_ready)(struct xenbus_device *dev); diff --git a/kernel/fail_function.c b/kernel/fail_function.c index a7ccd2930c5f..d971a0189319 100644 --- a/kernel/fail_function.c +++ b/kernel/fail_function.c @@ -163,10 +163,7 @@ static void fei_debugfs_add_attr(struct fei_attr *attr) static void fei_debugfs_remove_attr(struct fei_attr *attr) { - struct dentry *dir; - - dir = debugfs_lookup(attr->kp.symbol_name, fei_debugfs_dir); - debugfs_remove_recursive(dir); + debugfs_lookup_and_remove(attr->kp.symbol_name, fei_debugfs_dir); } static int fei_kprobe_handler(struct kprobe *kp, struct pt_regs *regs) diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 2df00b789b90..0408aab80941 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -51,6 +51,14 @@ static ssize_t cpu_byteorder_show(struct kobject *kobj, } KERNEL_ATTR_RO(cpu_byteorder); +/* address bits */ +static ssize_t address_bits_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%zu\n", sizeof(void *) * 8 /* CHAR_BIT */); +} +KERNEL_ATTR_RO(address_bits); + #ifdef CONFIG_UEVENT_HELPER /* uevent helper program, used during early boot */ static ssize_t uevent_helper_show(struct kobject *kobj, @@ -233,6 +241,7 @@ static struct attribute * kernel_attrs[] = { &fscaps_attr.attr, &uevent_seqnum_attr.attr, &cpu_byteorder_attr.attr, + &address_bits_attr.attr, #ifdef CONFIG_UEVENT_HELPER &uevent_helper_attr.attr, #endif diff --git a/lib/kobject.c b/lib/kobject.c index 985ee1c4f2c6..6e2f0bee3560 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -112,7 +112,7 @@ static int get_kobj_path_length(const struct kobject *kobj) return length; } -static void fill_kobj_path(const struct kobject *kobj, char *path, int length) +static int fill_kobj_path(const struct kobject *kobj, char *path, int length) { const struct kobject *parent; @@ -121,12 +121,16 @@ static void fill_kobj_path(const struct kobject *kobj, char *path, int length) int cur = strlen(kobject_name(parent)); /* back up enough to print this name with '/' */ length -= cur; + if (length <= 0) + return -EINVAL; memcpy(path + length, kobject_name(parent), cur); *(path + --length) = '/'; } pr_debug("kobject: '%s' (%p): %s: path = '%s'\n", kobject_name(kobj), kobj, __func__, path); + + return 0; } /** @@ -141,13 +145,17 @@ char *kobject_get_path(const struct kobject *kobj, gfp_t gfp_mask) char *path; int len; +retry: len = get_kobj_path_length(kobj); if (len == 0) return NULL; path = kzalloc(len, gfp_mask); if (!path) return NULL; - fill_kobj_path(kobj, path, len); + if (fill_kobj_path(kobj, path, len)) { + kfree(path); + goto retry; + } return path; } @@ -729,7 +737,7 @@ static void dynamic_kobj_release(struct kobject *kobj) kfree(kobj); } -static struct kobj_type dynamic_kobj_ktype = { +static const struct kobj_type dynamic_kobj_ktype = { .release = dynamic_kobj_release, .sysfs_ops = &kobj_sysfs_ops, }; @@ -913,7 +921,7 @@ static void kset_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t * kobject_get_ownership(kobj->parent, uid, gid); } -static struct kobj_type kset_ktype = { +static const struct kobj_type kset_ktype = { .sysfs_ops = &kobj_sysfs_ops, .release = kset_release, .get_ownership = kset_get_ownership, diff --git a/lib/test_firmware.c b/lib/test_firmware.c index e207bc08820d..05ed84c2fc4c 100644 --- a/lib/test_firmware.c +++ b/lib/test_firmware.c @@ -22,6 +22,7 @@ #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/delay.h> +#include <linux/kstrtox.h> #include <linux/kthread.h> #include <linux/vmalloc.h> #include <linux/efi_embedded_fw.h> @@ -50,7 +51,7 @@ struct test_batched_req { }; /** - * test_config - represents configuration for the test for different triggers + * struct test_config - represents configuration for the test for different triggers * * @name: the name of the firmware file to look for * @into_buf: when the into_buf is used if this is true @@ -358,7 +359,7 @@ static int test_dev_config_update_bool(const char *buf, size_t size, int ret; mutex_lock(&test_fw_mutex); - if (strtobool(buf, cfg) < 0) + if (kstrtobool(buf, cfg) < 0) ret = -EINVAL; else ret = size; diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c index 52f1acabd479..342452282719 100644 --- a/samples/kobject/kset-example.c +++ b/samples/kobject/kset-example.c @@ -185,7 +185,7 @@ ATTRIBUTE_GROUPS(foo_default); * release function, and the set of default attributes we want created * whenever a kobject of this type is registered with the kernel. */ -static struct kobj_type foo_ktype = { +static const struct kobj_type foo_ktype = { .sysfs_ops = &foo_sysfs_ops, .release = foo_release, .default_groups = foo_default_groups, diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch index 1eeb7b42c5b9..dc39d938ea77 100644 --- a/scripts/const_structs.checkpatch +++ b/scripts/const_structs.checkpatch @@ -35,6 +35,7 @@ iwl_ops kernel_param_ops kgdb_arch kgdb_io +kobj_type kset_uevent_ops lock_manager_operations machine_desc diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index c9579d97fbab..39fb8fe4e6ab 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c @@ -55,10 +55,10 @@ static int soundbus_probe(struct device *dev) } -static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int soundbus_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct soundbus_dev * soundbus_dev; - struct platform_device * of; + const struct soundbus_dev * soundbus_dev; + const struct platform_device * of; const char *compat; int retval = 0; int cplen, seen = 0; diff --git a/sound/hda/hda_bus_type.c b/sound/hda/hda_bus_type.c index eea6b63f8305..4cd94178df9f 100644 --- a/sound/hda/hda_bus_type.c +++ b/sound/hda/hda_bus_type.c @@ -65,7 +65,7 @@ static int hda_bus_match(struct device *dev, struct device_driver *drv) return 1; } -static int hda_uevent(struct device *dev, struct kobj_uevent_env *env) +static int hda_uevent(const struct device *dev, struct kobj_uevent_env *env) { char modalias[32]; diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index b7e5032b61c9..accc9d279ce5 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -204,7 +204,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_set_chip_name); * * Returns the size of string, like snprintf(), or a negative error code. */ -int snd_hdac_codec_modalias(struct hdac_device *codec, char *buf, size_t size) +int snd_hdac_codec_modalias(const struct hdac_device *codec, char *buf, size_t size) { return scnprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n", codec->vendor_id, codec->revision_id, codec->type); |