From 3022c6a1b4b76c40aab9dcdf5142c501f3d3ae8c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 25 Jun 2020 16:51:03 -0700 Subject: driver-core: Introduce DEVICE_ATTR_ADMIN_{RO,RW} A common pattern for using plain DEVICE_ATTR() instead of DEVICE_ATTR_RO() and DEVICE_ATTR_RW() is for attributes that want to limit read to only root. I.e. many users of DEVICE_ATTR() are specifying 0400 or 0600 for permissions. Given the expectation that CAP_SYS_ADMIN is needed to access these sensitive attributes and an explicit helper with the _ADMIN_ identifier for DEVICE_ATTR_ADMIN_{RO,RW}. Cc: "Rafael J. Wysocki" Signed-off-by: Dan Williams Link: https://lore.kernel.org/r/159312906372.1850128.11611897078988158727.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 4 ++++ include/linux/sysfs.h | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/include/linux/device.h b/include/linux/device.h index 15460a5ac024..d7c2570368fa 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -128,8 +128,12 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, __ATTR_PREALLOC(_name, _mode, _show, _store) #define DEVICE_ATTR_RW(_name) \ struct device_attribute dev_attr_##_name = __ATTR_RW(_name) +#define DEVICE_ATTR_ADMIN_RW(_name) \ + struct device_attribute dev_attr_##_name = __ATTR_RW_MODE(_name, 0600) #define DEVICE_ATTR_RO(_name) \ struct device_attribute dev_attr_##_name = __ATTR_RO(_name) +#define DEVICE_ATTR_ADMIN_RO(_name) \ + struct device_attribute dev_attr_##_name = __ATTR_RO_MODE(_name, 0400) #define DEVICE_ATTR_WO(_name) \ struct device_attribute dev_attr_##_name = __ATTR_WO(_name) #define DEVICE_ULONG_ATTR(_name, _mode, _var) \ diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 86067dbe7745..34e84122f635 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -123,6 +123,13 @@ struct attribute_group { .show = _name##_show, \ } +#define __ATTR_RW_MODE(_name, _mode) { \ + .attr = { .name = __stringify(_name), \ + .mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \ + .show = _name##_show, \ + .store = _name##_store, \ +} + #define __ATTR_WO(_name) { \ .attr = { .name = __stringify(_name), .mode = 0200 }, \ .store = _name##_store, \ -- cgit v1.2.3 From 63160c0a7f1df4420607c27793db0bc5f67ef95f Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2020 08:50:03 +0200 Subject: devres: remove stray space from devm_kmalloc() definition Use the preferred coding style for functions returning pointers. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20200629065008.27620-2-brgl@bgdev.pl Signed-off-by: Greg Kroah-Hartman --- drivers/base/devres.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 0bbb328bd17f..c34327219c34 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -807,7 +807,7 @@ static int devm_kmalloc_match(struct device *dev, void *res, void *data) * RETURNS: * Pointer to allocated memory on success, NULL on failure. */ -void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) +void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) { struct devres *dr; -- cgit v1.2.3 From dc2a633ccb608a1a8109ad0d488c98cc776bef72 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2020 08:50:04 +0200 Subject: devres: move the size check from alloc_dr() into a separate function We will perform the same size check in devm_krealloc(). Move the relevant code into a separate helper. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20200629065008.27620-3-brgl@bgdev.pl Signed-off-by: Greg Kroah-Hartman --- drivers/base/devres.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/base/devres.c b/drivers/base/devres.c index c34327219c34..1df1fb10b2d9 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -89,15 +89,23 @@ static struct devres_group * node_to_group(struct devres_node *node) return NULL; } +static bool check_dr_size(size_t size, size_t *tot_size) +{ + /* We must catch any near-SIZE_MAX cases that could overflow. */ + if (unlikely(check_add_overflow(sizeof(struct devres), + size, tot_size))) + return false; + + return true; +} + static __always_inline struct devres * alloc_dr(dr_release_t release, size_t size, gfp_t gfp, int nid) { size_t tot_size; struct devres *dr; - /* We must catch any near-SIZE_MAX cases that could overflow. */ - if (unlikely(check_add_overflow(sizeof(struct devres), size, - &tot_size))) + if (!check_dr_size(size, &tot_size)) return NULL; dr = kmalloc_node_track_caller(tot_size, gfp, nid); -- cgit v1.2.3 From 67dd0772396905a108c37202d4a5949ab69131a0 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2020 08:50:05 +0200 Subject: device: remove 'extern' attribute from function prototypes in device.h Functions are declared 'extern' implicitly by the compiler. There's no reason to prepend every prototype with it. Remove the 'extern' keyword from all function declarations in linux/device.h. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20200629065008.27620-4-brgl@bgdev.pl Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 223 ++++++++++++++++++++++++------------------------- 1 file changed, 107 insertions(+), 116 deletions(-) diff --git a/include/linux/device.h b/include/linux/device.h index d7c2570368fa..9a62f7f43d55 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -149,68 +149,66 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, struct device_attribute dev_attr_##_name = \ __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) -extern int device_create_file(struct device *device, - const struct device_attribute *entry); -extern void device_remove_file(struct device *dev, - const struct device_attribute *attr); -extern bool device_remove_file_self(struct device *dev, - const struct device_attribute *attr); -extern int __must_check device_create_bin_file(struct device *dev, +int device_create_file(struct device *device, + const struct device_attribute *entry); +void device_remove_file(struct device *dev, + const struct device_attribute *attr); +bool device_remove_file_self(struct device *dev, + const struct device_attribute *attr); +int __must_check device_create_bin_file(struct device *dev, const struct bin_attribute *attr); -extern void device_remove_bin_file(struct device *dev, - const struct bin_attribute *attr); +void device_remove_bin_file(struct device *dev, + const struct bin_attribute *attr); /* device resource management */ typedef void (*dr_release_t)(struct device *dev, void *res); typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data); #ifdef CONFIG_DEBUG_DEVRES -extern void *__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, - int nid, const char *name) __malloc; +void *__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, + int nid, const char *name) __malloc; #define devres_alloc(release, size, gfp) \ __devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release) #define devres_alloc_node(release, size, gfp, nid) \ __devres_alloc_node(release, size, gfp, nid, #release) #else -extern void *devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, - int nid) __malloc; +void *devres_alloc_node(dr_release_t release, size_t size, + gfp_t gfp, int nid) __malloc; static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp) { return devres_alloc_node(release, size, gfp, NUMA_NO_NODE); } #endif -extern void devres_for_each_res(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data, - void (*fn)(struct device *, void *, void *), - void *data); -extern void devres_free(void *res); -extern void devres_add(struct device *dev, void *res); -extern void *devres_find(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data); -extern void *devres_get(struct device *dev, void *new_res, - dr_match_t match, void *match_data); -extern void *devres_remove(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data); -extern int devres_destroy(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data); -extern int devres_release(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data); +void devres_for_each_res(struct device *dev, dr_release_t release, + dr_match_t match, void *match_data, + void (*fn)(struct device *, void *, void *), + void *data); +void devres_free(void *res); +void devres_add(struct device *dev, void *res); +void *devres_find(struct device *dev, dr_release_t release, + dr_match_t match, void *match_data); +void *devres_get(struct device *dev, void *new_res, + dr_match_t match, void *match_data); +void *devres_remove(struct device *dev, dr_release_t release, + dr_match_t match, void *match_data); +int devres_destroy(struct device *dev, dr_release_t release, + dr_match_t match, void *match_data); +int devres_release(struct device *dev, dr_release_t release, + dr_match_t match, void *match_data); /* devres group */ -extern void * __must_check devres_open_group(struct device *dev, void *id, - gfp_t gfp); -extern void devres_close_group(struct device *dev, void *id); -extern void devres_remove_group(struct device *dev, void *id); -extern int devres_release_group(struct device *dev, void *id); +void * __must_check devres_open_group(struct device *dev, void *id, gfp_t gfp); +void devres_close_group(struct device *dev, void *id); +void devres_remove_group(struct device *dev, void *id); +int devres_release_group(struct device *dev, void *id); /* managed devm_k.alloc/kfree for device drivers */ -extern void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) __malloc; -extern __printf(3, 0) -char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt, - va_list ap) __malloc; -extern __printf(3, 4) -char *devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...) __malloc; +void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) __malloc; +__printf(3, 0) char *devm_kvasprintf(struct device *dev, gfp_t gfp, + const char *fmt, va_list ap) __malloc; +__printf(3, 4) char *devm_kasprintf(struct device *dev, gfp_t gfp, + const char *fmt, ...) __malloc; static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) { return devm_kmalloc(dev, size, gfp | __GFP_ZERO); @@ -230,16 +228,14 @@ static inline void *devm_kcalloc(struct device *dev, { return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO); } -extern void devm_kfree(struct device *dev, const void *p); -extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc; -extern const char *devm_kstrdup_const(struct device *dev, - const char *s, gfp_t gfp); -extern void *devm_kmemdup(struct device *dev, const void *src, size_t len, - gfp_t gfp); +void devm_kfree(struct device *dev, const void *p); +char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc; +const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp); +void *devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp); -extern unsigned long devm_get_free_pages(struct device *dev, - gfp_t gfp_mask, unsigned int order); -extern void devm_free_pages(struct device *dev, unsigned long addr); +unsigned long devm_get_free_pages(struct device *dev, + gfp_t gfp_mask, unsigned int order); +void devm_free_pages(struct device *dev, unsigned long addr); void __iomem *devm_ioremap_resource(struct device *dev, const struct resource *res); @@ -655,8 +651,7 @@ static inline const char *dev_name(const struct device *dev) return kobject_name(&dev->kobj); } -extern __printf(2, 3) -int dev_set_name(struct device *dev, const char *name, ...); +__printf(2, 3) int dev_set_name(struct device *dev, const char *name, ...); #ifdef CONFIG_NUMA static inline int dev_to_node(struct device *dev) @@ -813,39 +808,38 @@ static inline bool dev_has_sync_state(struct device *dev) /* * High level routines for use by the bus drivers */ -extern int __must_check device_register(struct device *dev); -extern void device_unregister(struct device *dev); -extern void device_initialize(struct device *dev); -extern int __must_check device_add(struct device *dev); -extern void device_del(struct device *dev); -extern int device_for_each_child(struct device *dev, void *data, - int (*fn)(struct device *dev, void *data)); -extern int device_for_each_child_reverse(struct device *dev, void *data, - int (*fn)(struct device *dev, void *data)); -extern struct device *device_find_child(struct device *dev, void *data, - int (*match)(struct device *dev, void *data)); -extern struct device *device_find_child_by_name(struct device *parent, - const char *name); -extern int device_rename(struct device *dev, const char *new_name); -extern int device_move(struct device *dev, struct device *new_parent, - enum dpm_order dpm_order); -extern int device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid); -extern const char *device_get_devnode(struct device *dev, - umode_t *mode, kuid_t *uid, kgid_t *gid, - const char **tmp); +int __must_check device_register(struct device *dev); +void device_unregister(struct device *dev); +void device_initialize(struct device *dev); +int __must_check device_add(struct device *dev); +void device_del(struct device *dev); +int device_for_each_child(struct device *dev, void *data, + int (*fn)(struct device *dev, void *data)); +int device_for_each_child_reverse(struct device *dev, void *data, + int (*fn)(struct device *dev, void *data)); +struct device *device_find_child(struct device *dev, void *data, + int (*match)(struct device *dev, void *data)); +struct device *device_find_child_by_name(struct device *parent, + const char *name); +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); static inline bool device_supports_offline(struct device *dev) { return dev->bus && dev->bus->offline && dev->bus->online; } -extern void lock_device_hotplug(void); -extern void unlock_device_hotplug(void); -extern int lock_device_hotplug_sysfs(void); -extern int device_offline(struct device *dev); -extern int device_online(struct device *dev); -extern void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode); -extern void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode); +void lock_device_hotplug(void); +void unlock_device_hotplug(void); +int lock_device_hotplug_sysfs(void); +int device_offline(struct device *dev); +int device_online(struct device *dev); +void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode); +void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode); void device_set_of_node_from_dev(struct device *dev, const struct device *dev2); static inline int dev_num_vf(struct device *dev) @@ -858,14 +852,13 @@ static inline int dev_num_vf(struct device *dev) /* * Root device objects for grouping under /sys/devices */ -extern struct device *__root_device_register(const char *name, - struct module *owner); +struct device *__root_device_register(const char *name, struct module *owner); /* This is a macro to avoid include problems with THIS_MODULE */ #define root_device_register(name) \ __root_device_register(name, THIS_MODULE) -extern void root_device_unregister(struct device *root); +void root_device_unregister(struct device *root); static inline void *dev_get_platdata(const struct device *dev) { @@ -876,33 +869,31 @@ static inline void *dev_get_platdata(const struct device *dev) * Manual binding of a device to driver. See drivers/base/bus.c * for information on use. */ -extern int __must_check device_bind_driver(struct device *dev); -extern void device_release_driver(struct device *dev); -extern int __must_check device_attach(struct device *dev); -extern int __must_check driver_attach(struct device_driver *drv); -extern void device_initial_probe(struct device *dev); -extern int __must_check device_reprobe(struct device *dev); +int __must_check device_bind_driver(struct device *dev); +void device_release_driver(struct device *dev); +int __must_check device_attach(struct device *dev); +int __must_check driver_attach(struct device_driver *drv); +void device_initial_probe(struct device *dev); +int __must_check device_reprobe(struct device *dev); -extern bool device_is_bound(struct device *dev); +bool device_is_bound(struct device *dev); /* * Easy functions for dynamically creating devices on the fly */ -extern __printf(5, 6) -struct device *device_create(struct class *cls, struct device *parent, - dev_t devt, void *drvdata, - const char *fmt, ...); -extern __printf(6, 7) -struct device *device_create_with_groups(struct class *cls, - struct device *parent, dev_t devt, void *drvdata, - const struct attribute_group **groups, - const char *fmt, ...); -extern void device_destroy(struct class *cls, dev_t devt); - -extern int __must_check device_add_groups(struct device *dev, - const struct attribute_group **groups); -extern void device_remove_groups(struct device *dev, - const struct attribute_group **groups); +__printf(5, 6) struct device * +device_create(struct class *cls, struct device *parent, dev_t devt, + void *drvdata, const char *fmt, ...); +__printf(6, 7) struct device * +device_create_with_groups(struct class *cls, struct device *parent, dev_t devt, + void *drvdata, const struct attribute_group **groups, + const char *fmt, ...); +void device_destroy(struct class *cls, dev_t devt); + +int __must_check device_add_groups(struct device *dev, + const struct attribute_group **groups); +void device_remove_groups(struct device *dev, + const struct attribute_group **groups); static inline int __must_check device_add_group(struct device *dev, const struct attribute_group *grp) @@ -920,14 +911,14 @@ static inline void device_remove_group(struct device *dev, return device_remove_groups(dev, groups); } -extern int __must_check devm_device_add_groups(struct device *dev, +int __must_check devm_device_add_groups(struct device *dev, const struct attribute_group **groups); -extern void devm_device_remove_groups(struct device *dev, - const struct attribute_group **groups); -extern int __must_check devm_device_add_group(struct device *dev, - const struct attribute_group *grp); -extern void devm_device_remove_group(struct device *dev, - const struct attribute_group *grp); +void devm_device_remove_groups(struct device *dev, + const struct attribute_group **groups); +int __must_check devm_device_add_group(struct device *dev, + const struct attribute_group *grp); +void devm_device_remove_group(struct device *dev, + const struct attribute_group *grp); /* * Platform "fixup" functions - allow the platform to have their say @@ -944,21 +935,21 @@ extern int (*platform_notify_remove)(struct device *dev); * get_device - atomically increment the reference count for the device. * */ -extern struct device *get_device(struct device *dev); -extern void put_device(struct device *dev); -extern bool kill_device(struct device *dev); +struct device *get_device(struct device *dev); +void put_device(struct device *dev); +bool kill_device(struct device *dev); #ifdef CONFIG_DEVTMPFS -extern int devtmpfs_mount(void); +int devtmpfs_mount(void); #else static inline int devtmpfs_mount(void) { return 0; } #endif /* drivers/base/power/shutdown.c */ -extern void device_shutdown(void); +void device_shutdown(void); /* debugging and troubleshooting/diagnostic helpers. */ -extern const char *dev_driver_string(const struct device *dev); +const char *dev_driver_string(const struct device *dev); /* Device links interface. */ struct device_link *device_link_add(struct device *consumer, -- cgit v1.2.3 From cad064f1bd5237481d15b72b481809e3f0907dd9 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 29 Jun 2020 08:50:06 +0200 Subject: devres: handle zero size in devm_kmalloc() Make devm_kmalloc() behave similarly to non-managed kmalloc(): return ZERO_SIZE_PTR when requested size is 0. Update devm_kfree() to handle this case. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20200629065008.27620-5-brgl@bgdev.pl Signed-off-by: Greg Kroah-Hartman --- drivers/base/devres.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 1df1fb10b2d9..ed615d3b9cf1 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -819,6 +819,9 @@ void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) { struct devres *dr; + if (unlikely(!size)) + return ZERO_SIZE_PTR; + /* use raw alloc_dr for kmalloc caller tracing */ dr = alloc_dr(devm_kmalloc_release, size, gfp, dev_to_node(dev)); if (unlikely(!dr)) @@ -950,10 +953,10 @@ void devm_kfree(struct device *dev, const void *p) int rc; /* - * Special case: pointer to a string in .rodata returned by - * devm_kstrdup_const(). + * Special cases: pointer to a string in .rodata returned by + * devm_kstrdup_const() or NULL/ZERO ptr. */ - if (unlikely(is_kernel_rodata((unsigned long)p))) + if (unlikely(is_kernel_rodata((unsigned long)p) || ZERO_OR_NULL_PTR(p))) return; rc = devres_destroy(dev, devm_kmalloc_release, -- cgit v1.2.3 From 2fce60be06ca68b0b97b88b9ceb52ff102b0ea78 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 3 Jul 2020 00:11:07 +0200 Subject: firmware: improve description of firmware_request_nowarn The doubled 'however' is confusing. Simplify the comment a little and reformat the paragraph. Signed-off-by: Wolfram Sang Acked-by: Luis Chamberlain Link: https://lore.kernel.org/r/20200702221107.6562-1-wsa+renesas@sang-engineering.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_loader/main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index ca871b13524e..9da0c9d5f538 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -838,12 +838,12 @@ EXPORT_SYMBOL(request_firmware); * @name: name of firmware file * @device: device for which firmware is being loaded * - * This function is similar in behaviour to request_firmware(), except - * it doesn't produce warning messages when the file is not found. - * The sysfs fallback mechanism is enabled if direct filesystem lookup fails, - * however, however failures to find the firmware file with it are still - * suppressed. It is therefore up to the driver to check for the return value - * of this call and to decide when to inform the users of errors. + * This function is similar in behaviour to request_firmware(), except it + * doesn't produce warning messages when the file is not found. The sysfs + * fallback mechanism is enabled if direct filesystem lookup fails. However, + * failures to find the firmware file with it are still suppressed. It is + * therefore up to the driver to check for the return value of this call and to + * decide when to inform the users of errors. **/ int firmware_request_nowarn(const struct firmware **firmware, const char *name, struct device *device) -- cgit v1.2.3 From 0a2fae2aea4a21b59d4a920b9765aaa696270b16 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 3 Jul 2020 00:20:24 +0200 Subject: lib: update DEBUG_SHIRQ docs to match reality There is no extra interrupt when registering a shared interrupt handler since 2011. Update the Kconfig text to make it clear and to avoid wrong assumptions when debugging issues found by it. Fixes: 6d83f94db95c ("genirq: Disable the SHIRQ_DEBUG call in request_threaded_irq for now") Link: https://lore.kernel.org/linux-i2c/859e8211-2c56-8dd5-d6fb-33e4358e4128@pengutronix.de/T/#mf24d7070d7e0c8f17b6be6ceb51df94b7d7613b3 Reviewed-by: Krzysztof Kozlowski Acked-by: Andy Shevchenko Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20200702222024.6915-1-wsa+renesas@sang-engineering.com Signed-off-by: Greg Kroah-Hartman --- lib/Kconfig.debug | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 9ad9210d70a1..2bff6315224d 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -844,10 +844,10 @@ config DEBUG_SHIRQ bool "Debug shared IRQ handlers" depends on DEBUG_KERNEL help - Enable this to generate a spurious interrupt as soon as a shared - interrupt handler is registered, and just before one is deregistered. - Drivers ought to be able to handle interrupts coming in at those - points; some don't and need to be caught. + Enable this to generate a spurious interrupt just before a shared + interrupt handler is deregistered (generating one when registering + is currently disabled). Drivers need to handle this correctly. Some + don't and need to be caught. menu "Debug Oops, Lockups and Hangs" -- cgit v1.2.3 From e5711945c6415ab847b39ef89003ef68f9435bc6 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Tue, 2 Jun 2020 16:55:56 +1200 Subject: driver core: platform: need consistent spacing around '-' Fix the below checkpatch issue: ERROR: need consistent spacing around '-' (ctx:WxV) FILE: drivers/base/platform.c:1008: + len = acpi_device_modalias(dev, buf, PAGE_SIZE -1); ^ Signed-off-by: Barry Song Link: https://lore.kernel.org/r/20200602045556.66948-1-song.bao.hua@hisilicon.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index c0d0a5490ac6..3273a2fad4ad 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1019,7 +1019,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, if (len != -ENODEV) return len; - len = acpi_device_modalias(dev, buf, PAGE_SIZE -1); + len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); if (len != -ENODEV) return len; -- cgit v1.2.3 From 079ad2fb4bf9eba8a0aaab014b49705cd7f07c66 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Thu, 4 Jun 2020 19:46:46 +0200 Subject: kobject: Avoid premature parent object freeing in kobject_cleanup() If kobject_del() is invoked by kobject_cleanup() to delete the target kobject, it may cause its parent kobject to be freed before invoking the target kobject's ->release() method, which effectively means freeing the parent before dealing with the child entirely. That is confusing at best and it may also lead to functional issues if the callers of kobject_cleanup() are not careful enough about the order in which these calls are made, so avoid the problem by making kobject_cleanup() drop the last reference to the target kobject's parent at the end, after invoking the target kobject's ->release() method. [ rjw: Rewrite the subject and changelog, make kobject_cleanup() drop the parent reference only when __kobject_del() has been called. ] Reported-by: Naresh Kamboju Reported-by: kernel test robot Fixes: 7589238a8cf3 ("Revert "software node: Simplify software_node_release() function"") Suggested-by: Rafael J. Wysocki Signed-off-by: Heikki Krogerus Signed-off-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/1908555.IiAGLGrh1Z@kreacher Signed-off-by: Greg Kroah-Hartman --- lib/kobject.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/kobject.c b/lib/kobject.c index 1e4b7382a88e..3afb939f2a1c 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -599,14 +599,7 @@ out: } EXPORT_SYMBOL_GPL(kobject_move); -/** - * kobject_del() - Unlink kobject from hierarchy. - * @kobj: object. - * - * This is the function that should be called to delete an object - * successfully added via kobject_add(). - */ -void kobject_del(struct kobject *kobj) +static void __kobject_del(struct kobject *kobj) { struct kernfs_node *sd; const struct kobj_type *ktype; @@ -632,9 +625,23 @@ void kobject_del(struct kobject *kobj) kobj->state_in_sysfs = 0; kobj_kset_leave(kobj); - kobject_put(kobj->parent); kobj->parent = NULL; } + +/** + * kobject_del() - Unlink kobject from hierarchy. + * @kobj: object. + * + * This is the function that should be called to delete an object + * successfully added via kobject_add(). + */ +void kobject_del(struct kobject *kobj) +{ + struct kobject *parent = kobj->parent; + + __kobject_del(kobj); + kobject_put(parent); +} EXPORT_SYMBOL(kobject_del); /** @@ -670,6 +677,7 @@ EXPORT_SYMBOL(kobject_get_unless_zero); */ static void kobject_cleanup(struct kobject *kobj) { + struct kobject *parent = kobj->parent; struct kobj_type *t = get_ktype(kobj); const char *name = kobj->name; @@ -684,7 +692,10 @@ static void kobject_cleanup(struct kobject *kobj) if (kobj->state_in_sysfs) { pr_debug("kobject: '%s' (%p): auto cleanup kobject_del\n", kobject_name(kobj), kobj); - kobject_del(kobj); + __kobject_del(kobj); + } else { + /* avoid dropping the parent reference unnecessarily */ + parent = NULL; } if (t && t->release) { @@ -698,6 +709,8 @@ static void kobject_cleanup(struct kobject *kobj) pr_debug("kobject: '%s': free name\n", name); kfree_const(name); } + + kobject_put(parent); } #ifdef CONFIG_DEBUG_KOBJECT_RELEASE -- cgit v1.2.3 From 4a60406d3592373b8fd27ddfd010c5e62ad6c674 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Fri, 19 Jun 2020 15:00:45 +1200 Subject: driver core: platform: expose numa_node to users in sysfs Some platform devices like ARM SMMU are memory-mapped and populated by ACPI/IORT. In this case, NUMA topology of those platform devices are exported by firmware as well. Software might care about the numa_node of those devices in order to achieve NUMA locality. This patch will show the numa_node for this kind of devices in sysfs. For those platform devices without numa, numa_node won't be visible. Cc: Prime Zeng Cc: Robin Murphy Signed-off-by: Barry Song Link: https://lore.kernel.org/r/20200619030045.81956-1-song.bao.hua@hisilicon.com Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-bus-platform | 10 ++++++++++ drivers/base/platform.c | 26 +++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-platform b/Documentation/ABI/testing/sysfs-bus-platform index 5172a6124b27..194ca700e962 100644 --- a/Documentation/ABI/testing/sysfs-bus-platform +++ b/Documentation/ABI/testing/sysfs-bus-platform @@ -18,3 +18,13 @@ Description: devices to opt-out of driver binding using a driver_override name such as "none". Only a single driver may be specified in the override, there is no support for parsing delimiters. + +What: /sys/bus/platform/devices/.../numa_node +Date: June 2020 +Contact: Barry Song +Description: + This file contains the NUMA node to which the platform device + is attached. It won't be visible if the node is unknown. The + value comes from an ACPI _PXM method or a similar firmware + source. Initial users for this file would be devices like + arm smmu which are populated by arm64 acpi_iort. diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 3273a2fad4ad..e5d8a0503b4f 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1076,13 +1076,37 @@ static ssize_t driver_override_show(struct device *dev, } static DEVICE_ATTR_RW(driver_override); +static ssize_t numa_node_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", dev_to_node(dev)); +} +static DEVICE_ATTR_RO(numa_node); + +static umode_t platform_dev_attrs_visible(struct kobject *kobj, struct attribute *a, + int n) +{ + struct device *dev = container_of(kobj, typeof(*dev), kobj); + + if (a == &dev_attr_numa_node.attr && + dev_to_node(dev) == NUMA_NO_NODE) + return 0; + + return a->mode; +} static struct attribute *platform_dev_attrs[] = { &dev_attr_modalias.attr, + &dev_attr_numa_node.attr, &dev_attr_driver_override.attr, NULL, }; -ATTRIBUTE_GROUPS(platform_dev); + +static struct attribute_group platform_dev_group = { + .attrs = platform_dev_attrs, + .is_visible = platform_dev_attrs_visible, +}; +__ATTRIBUTE_GROUPS(platform_dev); static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) { -- cgit v1.2.3 From 35bd8c07db2ce8fd2834ef866240613a4ef982e7 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 1 Jun 2020 12:58:26 +0300 Subject: devres: keep both device name and resource name in pretty name Sometimes debugging a device is easiest using devmem on its register map, and that can be seen with /proc/iomem. But some device drivers have many memory regions. Take for example a networking switch. Its memory map used to look like this in /proc/iomem: 1fc000000-1fc3fffff : pcie@1f0000000 1fc000000-1fc3fffff : 0000:00:00.5 1fc010000-1fc01ffff : sys 1fc030000-1fc03ffff : rew 1fc060000-1fc0603ff : s2 1fc070000-1fc0701ff : devcpu_gcb 1fc080000-1fc0800ff : qs 1fc090000-1fc0900cb : ptp 1fc100000-1fc10ffff : port0 1fc110000-1fc11ffff : port1 1fc120000-1fc12ffff : port2 1fc130000-1fc13ffff : port3 1fc140000-1fc14ffff : port4 1fc150000-1fc15ffff : port5 1fc200000-1fc21ffff : qsys 1fc280000-1fc28ffff : ana But after the patch in Fixes: was applied, the information is now presented in a much more opaque way: 1fc000000-1fc3fffff : pcie@1f0000000 1fc000000-1fc3fffff : 0000:00:00.5 1fc010000-1fc01ffff : 0000:00:00.5 1fc030000-1fc03ffff : 0000:00:00.5 1fc060000-1fc0603ff : 0000:00:00.5 1fc070000-1fc0701ff : 0000:00:00.5 1fc080000-1fc0800ff : 0000:00:00.5 1fc090000-1fc0900cb : 0000:00:00.5 1fc100000-1fc10ffff : 0000:00:00.5 1fc110000-1fc11ffff : 0000:00:00.5 1fc120000-1fc12ffff : 0000:00:00.5 1fc130000-1fc13ffff : 0000:00:00.5 1fc140000-1fc14ffff : 0000:00:00.5 1fc150000-1fc15ffff : 0000:00:00.5 1fc200000-1fc21ffff : 0000:00:00.5 1fc280000-1fc28ffff : 0000:00:00.5 That patch made a fair comment that /proc/iomem might be confusing when it shows resources without an associated device, but we can do better than just hide the resource name altogether. Namely, we can print the device name _and_ the resource name. Like this: 1fc000000-1fc3fffff : pcie@1f0000000 1fc000000-1fc3fffff : 0000:00:00.5 1fc010000-1fc01ffff : 0000:00:00.5 sys 1fc030000-1fc03ffff : 0000:00:00.5 rew 1fc060000-1fc0603ff : 0000:00:00.5 s2 1fc070000-1fc0701ff : 0000:00:00.5 devcpu_gcb 1fc080000-1fc0800ff : 0000:00:00.5 qs 1fc090000-1fc0900cb : 0000:00:00.5 ptp 1fc100000-1fc10ffff : 0000:00:00.5 port0 1fc110000-1fc11ffff : 0000:00:00.5 port1 1fc120000-1fc12ffff : 0000:00:00.5 port2 1fc130000-1fc13ffff : 0000:00:00.5 port3 1fc140000-1fc14ffff : 0000:00:00.5 port4 1fc150000-1fc15ffff : 0000:00:00.5 port5 1fc200000-1fc21ffff : 0000:00:00.5 qsys 1fc280000-1fc28ffff : 0000:00:00.5 ana Fixes: 8d84b18f5678 ("devres: always use dev_name() in devm_ioremap_resource()") Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20200601095826.1757621-1-olteanv@gmail.com Signed-off-by: Greg Kroah-Hartman --- lib/devres.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/devres.c b/lib/devres.c index 6ef51f159c54..ca0d28727cce 100644 --- a/lib/devres.c +++ b/lib/devres.c @@ -119,6 +119,7 @@ __devm_ioremap_resource(struct device *dev, const struct resource *res, { resource_size_t size; void __iomem *dest_ptr; + char *pretty_name; BUG_ON(!dev); @@ -129,7 +130,15 @@ __devm_ioremap_resource(struct device *dev, const struct resource *res, size = resource_size(res); - if (!devm_request_mem_region(dev, res->start, size, dev_name(dev))) { + if (res->name) + pretty_name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", + dev_name(dev), res->name); + else + pretty_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); + if (!pretty_name) + return IOMEM_ERR_PTR(-ENOMEM); + + if (!devm_request_mem_region(dev, res->start, size, pretty_name)) { dev_err(dev, "can't request region for resource %pR\n", res); return IOMEM_ERR_PTR(-EBUSY); } -- cgit v1.2.3 From 7ae731a8441d70e5fb6144422a675bf1b2d6ace9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 9 Jun 2020 13:46:42 +0300 Subject: lib: devres: add a comment about the devm_of_iomap() function We recently introduced a bug when we tried to convert of_iomap() to devm_of_iomap(). The problem was that there were two drivers mapping the same io region. The first driver was using of_iomap() and the second driver was using devm_of_iomap() and the kernel booted fine. When we converted the first drive to use devm_of_iomap() then the second driver failed with -EBUSY and the kernel couldn't boot. Let's add a comment to prevent this sort of mistake in the future. Signed-off-by: Dan Carpenter Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20200609104642.GA43074@mwanda Signed-off-by: Greg Kroah-Hartman --- lib/devres.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/devres.c b/lib/devres.c index ca0d28727cce..ebb1573d9ae3 100644 --- a/lib/devres.c +++ b/lib/devres.c @@ -213,6 +213,12 @@ void __iomem *devm_ioremap_resource_wc(struct device *dev, * base = devm_of_iomap(&pdev->dev, node, 0, NULL); * if (IS_ERR(base)) * return PTR_ERR(base); + * + * Please Note: This is not a one-to-one replacement for of_iomap() because the + * of_iomap() function does not track whether the region is already mapped. If + * two drivers try to map the same memory, the of_iomap() function will succeed + * but the the devm_of_iomap() function will return -EBUSY. + * */ void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index, resource_size_t *size) -- cgit v1.2.3 From 5962b8b271e83fab0b57b337901b21ad1a64112a Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Mon, 8 Jun 2020 11:52:17 +0200 Subject: drivers: base: Convert to printk alias functions The file mixes printk calls together with calls to pr_*(). Covert to printk alias functions to unify the code. Signed-off-by: Matthias Brugger Link: https://lore.kernel.org/r/20200608095217.21162-2-matthias.bgg@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 57c68769e157..8c0d33e182fd 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -158,12 +158,12 @@ int driver_register(struct device_driver *drv) if ((drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)) - printk(KERN_WARNING "Driver '%s' needs updating - please use " + pr_warn("Driver '%s' needs updating - please use " "bus_type methods\n", drv->name); other = driver_find(drv->name, drv->bus); if (other) { - printk(KERN_ERR "Error: Driver '%s' is already registered, " + pr_err("Error: Driver '%s' is already registered, " "aborting...\n", drv->name); return -EBUSY; } -- cgit v1.2.3 From 55c7549819e438f40a3ef1d8ac5c38b73390bcb7 Mon Sep 17 00:00:00 2001 From: Matthias Maennich Date: Thu, 4 Jun 2020 18:41:45 +0200 Subject: scripts: add dummy report mode to add_namespace.cocci When running `make coccicheck` in report mode using the add_namespace.cocci file, it will fail for files that contain MODULE_LICENSE. Those match the replacement precondition, but spatch errors out as virtual.ns is not set. In order to fix that, add the virtual rule nsdeps and only do search and replace if that rule has been explicitly requested. In order to make spatch happy in report mode, we also need a dummy rule, as otherwise it errors out with "No rules apply". Using a script:python rule appears unrelated and odd, but this is the shortest I could come up with. Adjust scripts/nsdeps accordingly to set the nsdeps rule when run trough `make nsdeps`. Suggested-by: Julia Lawall Fixes: c7c4e29fb5a4 ("scripts: add_namespace: Fix coccicheck failed") Cc: YueHaibing Cc: jeyu@kernel.org Cc: cocci@systeme.lip6.fr Cc: stable@vger.kernel.org Signed-off-by: Matthias Maennich Reported-by: Shuah Khan Acked-by: Julia Lawall Link: https://lore.kernel.org/r/20200604164145.173925-1-maennich@google.com Signed-off-by: Greg Kroah-Hartman --- scripts/coccinelle/misc/add_namespace.cocci | 8 +++++++- scripts/nsdeps | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/coccinelle/misc/add_namespace.cocci b/scripts/coccinelle/misc/add_namespace.cocci index 99e93a6c2e24..cbf1614163cb 100644 --- a/scripts/coccinelle/misc/add_namespace.cocci +++ b/scripts/coccinelle/misc/add_namespace.cocci @@ -6,6 +6,7 @@ /// add a missing namespace tag to a module source file. /// +virtual nsdeps virtual report @has_ns_import@ @@ -16,10 +17,15 @@ MODULE_IMPORT_NS(ns); // Add missing imports, but only adjacent to a MODULE_LICENSE statement. // That ensures we are adding it only to the main module source file. -@do_import depends on !has_ns_import@ +@do_import depends on !has_ns_import && nsdeps@ declarer name MODULE_LICENSE; expression license; identifier virtual.ns; @@ MODULE_LICENSE(license); + MODULE_IMPORT_NS(ns); + +// Dummy rule for report mode that would otherwise be empty and make spatch +// fail ("No rules apply.") +@script:python depends on report@ +@@ diff --git a/scripts/nsdeps b/scripts/nsdeps index 03a8e7cbe6c7..dab4c1a0e27d 100644 --- a/scripts/nsdeps +++ b/scripts/nsdeps @@ -29,7 +29,7 @@ fi generate_deps_for_ns() { $SPATCH --very-quiet --in-place --sp-file \ - $srctree/scripts/coccinelle/misc/add_namespace.cocci -D ns=$1 $2 + $srctree/scripts/coccinelle/misc/add_namespace.cocci -D nsdeps -D ns=$1 $2 } generate_deps() { -- cgit v1.2.3 From 0d989da36b1512a6c61ebbd9b155969f0d2de436 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 21 Jun 2020 10:11:06 +0200 Subject: topology: mark a function as __init to save some memory 'topology_sysfs_init()' is only called via 'device_initcall'. It can be marked as __init to save a few bytes of memory. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20200621081106.881915-1-christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/base/topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 4e033d4cc0dc..ad8d33c6077b 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -133,7 +133,7 @@ static int topology_remove_dev(unsigned int cpu) return 0; } -static int topology_sysfs_init(void) +static int __init topology_sysfs_init(void) { return cpuhp_setup_state(CPUHP_TOPOLOGY_PREPARE, "base/topology:prepare", topology_add_dev, -- cgit v1.2.3 From 9dcbac84244f32ef6b2d4ed47f37c8228450b57b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 22 Jun 2020 11:21:08 +0300 Subject: software node: Use software_node_unregister() when unregistering group of nodes After the commit 46d26819a505 ("software node: implement software_node_unregister()") has been applied a new helper appears that may be utilised in other places. For time being there is one such place, i.e. in software_node_unregister_node_group() which will benefit of the clean up. Use software_node_unregister() when unregistering group of nodes. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200622082108.25577-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/swnode.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index e5eb27375416..010828fc785b 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -761,17 +761,13 @@ EXPORT_SYMBOL_GPL(software_node_register_node_group); */ void software_node_unregister_node_group(const struct software_node **node_group) { - struct swnode *swnode; unsigned int i; if (!node_group) return; - for (i = 0; node_group[i]; i++) { - swnode = software_node_to_swnode(node_group[i]); - if (swnode) - fwnode_remove_software_node(&swnode->fwnode); - } + for (i = 0; node_group[i]; i++) + software_node_unregister(node_group[i]); } EXPORT_SYMBOL_GPL(software_node_unregister_node_group); -- cgit v1.2.3 From 105fbc229b775b69796cd20f53b609732c67c193 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 3 Jul 2020 20:44:56 -0700 Subject: Documentation/driver-api: driver-model/platform: drop doubled word Drop the doubled word "that". Signed-off-by: Randy Dunlap Cc: Jonathan Corbet Cc: linux-doc@vger.kernel.org Cc: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20200704034502.17199-12-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/driver-model/platform.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/driver-api/driver-model/platform.rst b/Documentation/driver-api/driver-model/platform.rst index 334dd4071ae4..1fe5c6c6199c 100644 --- a/Documentation/driver-api/driver-model/platform.rst +++ b/Documentation/driver-api/driver-model/platform.rst @@ -108,7 +108,7 @@ field to hold additional information. Embedded systems frequently need one or more clocks for platform devices, which are normally kept off until they're actively needed (to save power). -System setup also associates those clocks with the device, so that that +System setup also associates those clocks with the device, so that calls to clk_get(&pdev->dev, clock_name) return them as needed. -- cgit v1.2.3 From 40ba2cde77e764bd0dfe0c4098654d55a005fd7d Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Tue, 23 Jun 2020 10:57:00 +0800 Subject: drivers/base/memory: init_memory_block() first parameter is not necessary The first parameter of init_memory_block() is intended to retrieve the memory_block initiated. But now, we never use it. Drop it for now. Signed-off-by: Wei Yang Link: https://lore.kernel.org/r/20200623025701.2016-1-richard.weiyang@linux.alibaba.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/memory.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 2b09b68b9f78..35f9a1aa0a2e 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -570,8 +570,7 @@ int register_memory(struct memory_block *memory) return ret; } -static int init_memory_block(struct memory_block **memory, - unsigned long block_id, unsigned long state) +static int init_memory_block(unsigned long block_id, unsigned long state) { struct memory_block *mem; unsigned long start_pfn; @@ -594,14 +593,12 @@ static int init_memory_block(struct memory_block **memory, ret = register_memory(mem); - *memory = mem; return ret; } static int add_memory_block(unsigned long base_section_nr) { int section_count = 0; - struct memory_block *mem; unsigned long nr; for (nr = base_section_nr; nr < base_section_nr + sections_per_block; @@ -611,7 +608,7 @@ static int add_memory_block(unsigned long base_section_nr) if (section_count == 0) return 0; - return init_memory_block(&mem, base_memory_block_id(base_section_nr), + return init_memory_block(base_memory_block_id(base_section_nr), MEM_ONLINE); } @@ -647,7 +644,7 @@ int create_memory_block_devices(unsigned long start, unsigned long size) return -EINVAL; for (block_id = start_block_id; block_id != end_block_id; block_id++) { - ret = init_memory_block(&mem, block_id, MEM_OFFLINE); + ret = init_memory_block(block_id, MEM_OFFLINE); if (ret) break; } -- cgit v1.2.3 From 178bdbed3e0cebb7c04e37695dfa638aa8dafed3 Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Tue, 23 Jun 2020 10:57:01 +0800 Subject: drivers/base/memory: rename base_memory_block_id to memory_block_id memory_block may have a larger granularity than section, this is why we have base_section_nr. But base_memory_block_id seems a little misleading, since there is no larger granularity concept which groups several memory_block. What we need here is the exact memory_block_id to a section_nr. Let's rename it to make it more precise. Signed-off-by: Wei Yang Link: https://lore.kernel.org/r/20200623025701.2016-2-richard.weiyang@linux.alibaba.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/memory.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 35f9a1aa0a2e..4db3c660de83 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -50,14 +50,14 @@ int memhp_online_type_from_str(const char *str) static int sections_per_block; -static inline unsigned long base_memory_block_id(unsigned long section_nr) +static inline unsigned long memory_block_id(unsigned long section_nr) { return section_nr / sections_per_block; } static inline unsigned long pfn_to_block_id(unsigned long pfn) { - return base_memory_block_id(pfn_to_section_nr(pfn)); + return memory_block_id(pfn_to_section_nr(pfn)); } static inline unsigned long phys_to_block_id(unsigned long phys) @@ -517,7 +517,7 @@ static struct memory_block *find_memory_block_by_id(unsigned long block_id) */ struct memory_block *find_memory_block(struct mem_section *section) { - unsigned long block_id = base_memory_block_id(__section_nr(section)); + unsigned long block_id = memory_block_id(__section_nr(section)); return find_memory_block_by_id(block_id); } @@ -608,7 +608,7 @@ static int add_memory_block(unsigned long base_section_nr) if (section_count == 0) return 0; - return init_memory_block(base_memory_block_id(base_section_nr), + return init_memory_block(memory_block_id(base_section_nr), MEM_ONLINE); } -- cgit v1.2.3 From c80a67bd5d13e691f730115615885736acc5f1a7 Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Thu, 9 Jul 2020 05:40:33 +0000 Subject: debugfs: file: Remove unnecessary cast in kfree() Remove unnecassary casts in the argument to kfree. Signed-off-by: Xu Wang Link: https://lore.kernel.org/r/20200709054033.30148-1-vulab@iscas.ac.cn Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index ae49a55bda00..3753c4c484fc 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -273,7 +273,7 @@ static int full_proxy_release(struct inode *inode, struct file *filp) r = real_fops->release(inode, filp); replace_fops(filp, d_inode(dentry)->i_fop); - kfree((void *)proxy_fops); + kfree(proxy_fops); fops_put(real_fops); return r; } -- cgit v1.2.3 From fe940d7362e6d7a5e5086581d0462e00ba766992 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 8 Jul 2020 14:12:22 +0200 Subject: driver core: Drop mention of obsolete bus rwsem from kernel-doc 15 years ago, commit 6eded061b126 ("Fix up bus code and remove use of rwsem") removed the bus rwsem, but left over a reference to it in a kernel-doc comment. Drop it. Signed-off-by: Lukas Wunner Link: https://lore.kernel.org/r/b1af31b0e351bcbc056fe1ec44500737a7998d43.1594210157.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 9a1d940342ac..2aef1e4ce60a 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -430,10 +430,9 @@ static void driver_sysfs_remove(struct device *dev) * Allow manual attachment of a driver to a device. * Caller must have already set @dev->driver. * - * Note that this does not modify the bus reference count - * nor take the bus's rwsem. Please verify those are accounted - * for before calling this. (It is ok to call with no other effort - * from a driver's probe() method.) + * Note that this does not modify the bus reference count. + * Please verify that is accounted for before calling this. + * (It is ok to call with no other effort from a driver's probe() method.) * * This function must be called with the device lock held. */ -- cgit v1.2.3 From 287905e68dd29873bcb7986a8290cd1e4cfde600 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Thu, 21 May 2020 12:17:58 -0700 Subject: driver core: Expose device link details in sysfs It's helpful to be able to look at device link details from sysfs. So, expose it in sysfs. Say device-A is supplier of device-B. These are the additional files this patch would create: /sys/class/devlink/device-A:device-B/ auto_remove_on consumer/ -> .../device-B/ runtime_pm status supplier/ -> .../device-A/ sync_state_only /sys/devices/.../device-A/ consumer:device-B/ -> /sys/class/devlink/device-A:device-B/ /sys/devices/.../device-B/ supplier:device-A/ -> /sys/class/devlink/device-A:device-B/ That way: To get a list of all the device link in the system: ls /sys/class/devlink/ To get the consumer names and links of a device: ls -d /sys/devices/.../device-X/consumer:* To get the supplier names and links of a device: ls -d /sys/devices/.../device-X/supplier:* Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20200521191800.136035-2-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-class-devlink | 126 ++++++++++++++ Documentation/ABI/testing/sysfs-devices-consumer | 8 + Documentation/ABI/testing/sysfs-devices-supplier | 8 + drivers/base/core.c | 211 ++++++++++++++++++++++- include/linux/device.h | 58 ++++--- 5 files changed, 375 insertions(+), 36 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-devlink create mode 100644 Documentation/ABI/testing/sysfs-devices-consumer create mode 100644 Documentation/ABI/testing/sysfs-devices-supplier diff --git a/Documentation/ABI/testing/sysfs-class-devlink b/Documentation/ABI/testing/sysfs-class-devlink new file mode 100644 index 000000000000..3a24973abb83 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-devlink @@ -0,0 +1,126 @@ +What: /sys/class/devlink/.../ +Date: May 2020 +Contact: Saravana Kannan +Description: + Provide a place in sysfs for the device link objects in the + kernel at any given time. The name of a device link directory, + denoted as ... above, is of the form : + where is the supplier device name and is + the consumer device name. + +What: /sys/class/devlink/.../auto_remove_on +Date: May 2020 +Contact: Saravana Kannan +Description: + This file indicates if the device link will ever be + automatically removed by the driver core when the consumer and + supplier devices themselves are still present. + + This will be one of the following strings: + + 'consumer unbind' + 'supplier unbind' + 'never' + + 'consumer unbind' means the device link will be removed when + the consumer's driver is unbound from the consumer device. + + 'supplier unbind' means the device link will be removed when + the supplier's driver is unbound from the supplier device. + + 'never' means the device link will not be automatically removed + when as long as the supplier and consumer devices themselves + are still present. + +What: /sys/class/devlink/.../consumer +Date: May 2020 +Contact: Saravana Kannan +Description: + This file is a symlink to the consumer device's sysfs directory. + +What: /sys/class/devlink/.../runtime_pm +Date: May 2020 +Contact: Saravana Kannan +Description: + This file indicates if the device link has any impact on the + runtime power management behavior of the consumer and supplier + devices. For example: Making sure the supplier doesn't enter + runtime suspend while the consumer is active. + + This will be one of the following strings: + + '0' - Does not affect runtime power management + '1' - Affects runtime power management + +What: /sys/class/devlink/.../status +Date: May 2020 +Contact: Saravana Kannan +Description: + This file indicates the status of the device link. The status + of a device link is affected by whether the supplier and + consumer devices have been bound to their corresponding + drivers. The status of a device link also affects the binding + and unbinding of the supplier and consumer devices with their + drivers and also affects whether the software state of the + supplier device is synced with the hardware state of the + supplier device after boot up. + See also: sysfs-devices-state_synced. + + This will be one of the following strings: + + 'not tracked' + 'dormant' + 'available' + 'consumer probing' + 'active' + 'supplier unbinding' + 'unknown' + + 'not tracked' means this device link does not track the status + and has no impact on the binding, unbinding and syncing the + hardware and software device state. + + 'dormant' means the supplier and the consumer devices have not + bound to their driver. + + 'available' means the supplier has bound to its driver and is + available to supply resources to the consumer device. + + 'consumer probing' means the consumer device is currently + trying to bind to its driver. + + 'active' means the supplier and consumer devices have both + bound successfully to their drivers. + + 'supplier unbinding' means the supplier devices is currently in + the process of unbinding from its driver. + + 'unknown' means the state of the device link is not any of the + above. If this is ever the value, there's a bug in the kernel. + +What: /sys/class/devlink/.../supplier +Date: May 2020 +Contact: Saravana Kannan +Description: + This file is a symlink to the supplier device's sysfs directory. + +What: /sys/class/devlink/.../sync_state_only +Date: May 2020 +Contact: Saravana Kannan +Description: + This file indicates if the device link is limited to only + affecting the syncing of the hardware and software state of the + supplier device. + + This will be one of the following strings: + + '0' + '1' - Affects runtime power management + + '0' means the device link can affect other device behaviors + like binding/unbinding, suspend/resume, runtime power + management, etc. + + '1' means the device link will only affect the syncing of + hardware and software state of the supplier device after boot + up and doesn't not affect other behaviors of the devices. diff --git a/Documentation/ABI/testing/sysfs-devices-consumer b/Documentation/ABI/testing/sysfs-devices-consumer new file mode 100644 index 000000000000..1f06d74d1c3c --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-consumer @@ -0,0 +1,8 @@ +What: /sys/devices/.../consumer: +Date: May 2020 +Contact: Saravana Kannan +Description: + The /sys/devices/.../consumer: are symlinks to device + links where this device is the supplier. denotes the + name of the consumer in that device link. There can be zero or + more of these symlinks for a given device. diff --git a/Documentation/ABI/testing/sysfs-devices-supplier b/Documentation/ABI/testing/sysfs-devices-supplier new file mode 100644 index 000000000000..a919e0db5e90 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-supplier @@ -0,0 +1,8 @@ +What: /sys/devices/.../supplier: +Date: May 2020 +Contact: Saravana Kannan +Description: + The /sys/devices/.../supplier: are symlinks to device + links where this device is the consumer. denotes the + name of the supplier in that device link. There can be zero or + more of these symlinks for a given device. diff --git a/drivers/base/core.c b/drivers/base/core.c index 67d39a90b45c..ca6403343515 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -235,6 +235,186 @@ void device_pm_move_to_tail(struct device *dev) device_links_read_unlock(idx); } +#define to_devlink(dev) container_of((dev), struct device_link, link_dev) + +static ssize_t status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char *status; + + switch (to_devlink(dev)->status) { + case DL_STATE_NONE: + status = "not tracked"; break; + case DL_STATE_DORMANT: + status = "dormant"; break; + case DL_STATE_AVAILABLE: + status = "available"; break; + case DL_STATE_CONSUMER_PROBE: + status = "consumer probing"; break; + case DL_STATE_ACTIVE: + status = "active"; break; + case DL_STATE_SUPPLIER_UNBIND: + status = "supplier unbinding"; break; + default: + status = "unknown"; break; + } + return sprintf(buf, "%s\n", status); +} +static DEVICE_ATTR_RO(status); + +static ssize_t auto_remove_on_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device_link *link = to_devlink(dev); + char *str; + + if (link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) + str = "supplier unbind"; + else if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) + str = "consumer unbind"; + else + str = "never"; + + return sprintf(buf, "%s\n", str); +} +static DEVICE_ATTR_RO(auto_remove_on); + +static ssize_t runtime_pm_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device_link *link = to_devlink(dev); + + return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_PM_RUNTIME)); +} +static DEVICE_ATTR_RO(runtime_pm); + +static ssize_t sync_state_only_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device_link *link = to_devlink(dev); + + return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_SYNC_STATE_ONLY)); +} +static DEVICE_ATTR_RO(sync_state_only); + +static struct attribute *devlink_attrs[