From 8afbb4273977f055db219a22daaafe64be10fb95 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 9 Jan 2023 18:58:05 +0100 Subject: [PATCH 001/124] driver core: make bus_get_device_klist() static No one calls this function outside of drivers/base/bus.c so make it static so it does not need to be exported anymore. Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230109175810.2965448-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 3 +-- include/linux/device/bus.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 4ec6dbab73be5c..4425f962bf5161 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -897,11 +897,10 @@ struct kset *bus_get_kset(struct bus_type *bus) } EXPORT_SYMBOL_GPL(bus_get_kset); -struct klist *bus_get_device_klist(struct bus_type *bus) +static struct klist *bus_get_device_klist(struct bus_type *bus) { return &bus->p->klist_devices; } -EXPORT_SYMBOL_GPL(bus_get_device_klist); /* * Yes, this forcibly breaks the klist abstraction temporarily. It diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index d8b29ccd07e564..01077c503d6111 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -287,6 +287,5 @@ extern int bus_unregister_notifier(struct bus_type *bus, #define BUS_NOTIFY_DRIVER_NOT_BOUND 0x00000008 /* driver fails to be bound */ extern struct kset *bus_get_kset(struct bus_type *bus); -extern struct klist *bus_get_device_klist(struct bus_type *bus); #endif From a9efdd2519edd7df84afd075b65ca6428dcb0039 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 9 Jan 2023 18:58:06 +0100 Subject: [PATCH 002/124] driver core: remove subsys_find_device_by_id() This function has not been called by any code in the kernel tree in many many years so remove it as it is unused. Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230109175810.2965448-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 41 -------------------------------------- include/linux/device/bus.h | 2 -- 2 files changed, 43 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 4425f962bf5161..f8eb882bbf37c8 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -339,47 +339,6 @@ struct device *bus_find_device(struct bus_type *bus, } 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); diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index 01077c503d6111..3b1a2066afcdb1 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -250,8 +250,6 @@ bus_find_device_by_acpi_dev(struct bus_type *bus, const void *adev) } #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, void *data, int (*fn)(struct device_driver *, void *)); void bus_sort_breadthfirst(struct bus_type *bus, From 2e45fc5502af9826617a96fe63aee055002cac97 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 9 Jan 2023 18:58:07 +0100 Subject: [PATCH 003/124] driver core: make subsys_dev_iter_init() static No one outside of drivers/base/bus.c calls this function so make it static and remove the exported symbol. Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230109175810.2965448-3-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 5 ++--- include/linux/device/bus.h | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index f8eb882bbf37c8..f781124fdf3130 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -923,8 +923,8 @@ 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 bus_type *subsys, + struct device *start, const struct device_type *type) { struct klist_node *start_knode = NULL; @@ -933,7 +933,6 @@ void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys, klist_iter_init_node(&subsys->p->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 diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index 3b1a2066afcdb1..67cb5b29f62d2f 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -154,10 +154,6 @@ 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); From 38cdadefa2feecc9e7aa5f67bc4aea5b9a8ca59f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 9 Jan 2023 18:58:08 +0100 Subject: [PATCH 004/124] driver core: make subsys_dev_iter_next() static The function subsys_dev_iter_next() is only used in drivers/base/bus.c so make it static to that file and remove the global export. Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230109175810.2965448-4-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 3 +-- include/linux/device/bus.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index f781124fdf3130..f0aacb3b1bc624 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -946,7 +946,7 @@ static void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type * * 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; @@ -960,7 +960,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 diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index 67cb5b29f62d2f..4f994d8fce0c2b 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -154,7 +154,6 @@ struct subsys_dev_iter { struct klist_iter ki; 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, From af6d0743599e594cb2cec3f1a6d2600a57d1d375 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 9 Jan 2023 18:58:09 +0100 Subject: [PATCH 005/124] driver core: make subsys_dev_iter_exit() static The function subsys_dev_iter_exit() is not used outside of drivers/base/bus.c so make it static to that file and remove the global export. Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230109175810.2965448-5-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 3 +-- include/linux/device/bus.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index f0aacb3b1bc624..bde52fd1d3e3c5 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -968,11 +968,10 @@ static struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter) * 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) { diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index 4f994d8fce0c2b..848d49f4cc0919 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -154,7 +154,6 @@ struct subsys_dev_iter { struct klist_iter ki; const struct device_type *type; }; -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 (*fn)(struct device *dev, void *data)); From b0a8a59a1c44c07807afe50c6bd21a33c9ec98b7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 9 Jan 2023 18:58:10 +0100 Subject: [PATCH 006/124] driver core: move struct subsys_dev_iter to a local file struct subsys_dev_iter is not used by any code outside of drivers/base/bus.c so move it into that file and out of the global bus.h file. Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230109175810.2965448-6-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 5 +++++ include/linux/device/bus.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index bde52fd1d3e3c5..428c26c6b615e1 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -911,6 +911,11 @@ void bus_sort_breadthfirst(struct bus_type *bus, } 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 diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index 848d49f4cc0919..d529f644e92b07 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -150,11 +150,6 @@ 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; -}; - int bus_for_each_dev(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, From f6837f34a34973ef6600c08195ed300e24e97317 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 5 Dec 2022 11:49:04 +0800 Subject: [PATCH 007/124] driver core: fix potential null-ptr-deref in device_add() I got the following null-ptr-deref report while doing fault injection test: BUG: kernel NULL pointer dereference, address: 0000000000000058 CPU: 2 PID: 278 Comm: 37-i2c-ds2482 Tainted: G B W N 6.1.0-rc3+ RIP: 0010:klist_put+0x2d/0xd0 Call Trace: klist_remove+0xf1/0x1c0 device_release_driver_internal+0x196/0x210 bus_remove_device+0x1bd/0x240 device_add+0xd3d/0x1100 w1_add_master_device+0x476/0x490 [wire] ds2482_probe+0x303/0x3e0 [ds2482] This is how it happened: w1_alloc_dev() // The dev->driver is set to w1_master_driver. memcpy(&dev->dev, device, sizeof(struct device)); device_add() bus_add_device() dpm_sysfs_add() // It fails, calls bus_remove_device. // error path bus_remove_device() // The dev->driver is not null, but driver is not bound. __device_release_driver() klist_remove(&dev->p->knode_driver) <-- It causes null-ptr-deref. // normal path bus_probe_device() // It's not called yet. device_bind_driver() If dev->driver is set, in the error path after calling bus_add_device() in device_add(), bus_remove_device() is called, then the device will be detached from driver. But device_bind_driver() is not called yet, so it causes null-ptr-deref while access the 'knode_driver'. To fix this, set dev->driver to null in the error path before calling bus_remove_device(). Fixes: 57eee3d23e88 ("Driver core: Call device_pm_add() after bus_add_device() in device_add()") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221205034904.2077765-1-yangyingliang@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index a3e14143ec0cfd..506289e6b04dd1 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3513,6 +3513,7 @@ int device_add(struct device *dev) device_pm_remove(dev); dpm_sysfs_remove(dev); DPMError: + dev->driver = NULL; bus_remove_device(dev); BusError: device_remove_attrs(dev); From 504fa212d7030fb1c042290dc2eb92b21515573a Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 28 Dec 2022 00:21:52 +0100 Subject: [PATCH 008/124] driver core: Make driver_deferred_probe_timeout a static variable It is not used outside of its compilation unit, so there's no need to export this variable. Signed-off-by: Javier Martinez Canillas Reviewed-by: Andrew Halaney Acked-by: John Stultz Link: https://lore.kernel.org/r/20221227232152.3094584-1-javierm@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 6 ++---- include/linux/device/driver.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index e9b2f9c25efe48..69daf9d414ebe1 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; diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index 2114d65b862fc6..50d0a416a5e74d 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); From 3bb2a01caa813d3a1845d378bbe4169ef280d394 Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Tue, 20 Dec 2022 09:21:43 +0800 Subject: [PATCH 009/124] kobject: Fix slab-out-of-bounds in fill_kobj_path() In kobject_get_path(), if kobj->name is changed between calls get_kobj_path_length() and fill_kobj_path() and the length becomes longer, then fill_kobj_path() will have an out-of-bounds bug. The actual current problem occurs when the ixgbe probe. In ixgbe_mii_bus_init(), if the length of netdev->dev.kobj.name length becomes longer, out-of-bounds will occur. cpu0 cpu1 ixgbe_probe register_netdev(netdev) netdev_register_kobject device_add kobject_uevent // Sending ADD events systemd-udevd // rename netdev dev_change_name device_rename kobject_rename ixgbe_mii_bus_init | mdiobus_register | __mdiobus_register | device_register | device_add | kobject_uevent | kobject_get_path | len = get_kobj_path_length // old name | path = kzalloc(len, gfp_mask); | kobj->name = name; /* name length becomes * longer */ fill_kobj_path /* kobj path length is * longer than path, * resulting in out of * bounds when filling path */ This is the kasan report: ================================================================== BUG: KASAN: slab-out-of-bounds in fill_kobj_path+0x50/0xc0 Write of size 7 at addr ff1100090573d1fd by task kworker/28:1/673 Workqueue: events work_for_cpu_fn Call Trace: dump_stack_lvl+0x34/0x48 print_address_description.constprop.0+0x86/0x1e7 print_report+0x36/0x4f kasan_report+0xad/0x130 kasan_check_range+0x35/0x1c0 memcpy+0x39/0x60 fill_kobj_path+0x50/0xc0 kobject_get_path+0x5a/0xc0 kobject_uevent_env+0x140/0x460 device_add+0x5c7/0x910 __mdiobus_register+0x14e/0x490 ixgbe_probe.cold+0x441/0x574 [ixgbe] local_pci_probe+0x78/0xc0 work_for_cpu_fn+0x26/0x40 process_one_work+0x3b6/0x6a0 worker_thread+0x368/0x520 kthread+0x165/0x1a0 ret_from_fork+0x1f/0x30 This reproducer triggers that bug: while: do rmmod ixgbe sleep 0.5 modprobe ixgbe sleep 0.5 When calling fill_kobj_path() to fill path, if the name length of kobj becomes longer, return failure and retry. This fixes the problem. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Wang Hai Link: https://lore.kernel.org/r/20221220012143.52141-1-wanghai38@huawei.com Signed-off-by: Greg Kroah-Hartman --- lib/kobject.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/kobject.c b/lib/kobject.c index 985ee1c4f2c609..d20ce15eec2d05 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; } From 7bbb89b420d9e290cb34864832de8fcdf2c140dc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 10:33:27 +0100 Subject: [PATCH 010/124] driver core: change to_subsys_private() to use container_of_const() The macro to_subsys_private() needs to switch to using container_of_const() as it turned out to being incorrectly casting a const pointer to a non-const one. Make this change and fix up the one offending user to be correctly handling a const pointer properly. Cc: "Rafael J. Wysocki" Reviewed-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20230111093327.3955063-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 2 +- drivers/base/class.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 7d4803c03d3e61..2eb722d89f1064 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -53,7 +53,7 @@ struct subsys_private { struct kset glue_dirs; struct class *class; }; -#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) struct driver_private { struct kobject kobj; diff --git a/drivers/base/class.c b/drivers/base/class.c index 86ec554cfe6041..3366da9c3ff6eb 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -64,7 +64,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; From 5c5a7680e67ba6fbbb5f4d79fa41485450c1985c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 9 Dec 2022 16:09:14 +0100 Subject: [PATCH 011/124] platform: Provide a remove callback that returns no value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct platform_driver::remove returning an integer made driver authors expect that returning an error code was proper error handling. However the driver core ignores the error and continues to remove the device because there is nothing the core could do anyhow and reentering the remove callback again is only calling for trouble. So this is an source for errors typically yielding resource leaks in the error path. As there are too many platform drivers to neatly convert them all to return void in a single go, do it in several steps after this patch: a) Convert all drivers to implement .remove_new() returning void instead of .remove() returning int; b) Change struct platform_driver::remove() to return void and so make it identical to .remove_new(); c) Change all drivers back to .remove() now with the better prototype; d) drop struct platform_driver::remove_new(). While this touches all drivers eventually twice, steps a) and c) can be done one driver after another and so reduces coordination efforts immensely and simplifies review. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20221209150914.3557650-1-u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 4 +++- include/linux/platform_device.h | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 968f3d71eeab2e..a4938d1c8fe1d3 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1416,7 +1416,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/include/linux/platform_device.h b/include/linux/platform_device.h index b0d5a253156ece..b845fd83f429bb 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 *); From 1c856b4b114331d13ee01e92d3fa638797759748 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Dec 2022 11:49:19 +0200 Subject: [PATCH 012/124] media: ipu3-cio2: Don't dereference fwnode handle Use acpi_fwnode_handle() instead of dereferencing an fwnode handle directly, which is a better coding practice. Signed-off-by: Andy Shevchenko Acked-by: Sakari Ailus Tested-by: Daniel Scally Acked-by: Heikki Krogerus Reviewed-by: Daniel Scally Link: https://lore.kernel.org/r/20221228094922.84119-2-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index df6c94da2f6ad8..18974a72e94ac8 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -263,7 +263,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; @@ -322,7 +322,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); From 24e5149217ddaab7c7809ad8a9363d54a61b77db Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Dec 2022 11:49:20 +0200 Subject: [PATCH 013/124] media: ipu3-cio2: Convert to use software_node_register_node_group() The currently used software_node_register_nodes() is going to be removed. Prepare driver by switching to a new API. Signed-off-by: Andy Shevchenko Acked-by: Sakari Ailus Tested-by: Daniel Scally Acked-by: Heikki Krogerus Reviewed-by: Daniel Scally Link: https://lore.kernel.org/r/20221228094922.84119-3-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 21 ++++++++++++++++++--- drivers/media/pci/intel/ipu3/cio2-bridge.h | 5 +++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 18974a72e94ac8..dfefe0d8aa959e 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); @@ -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; @@ -337,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 4418cbd08208dc..b93b749c65bda3 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; From d903bca1897e27e6bebb3522d44697c478cc0c4b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Dec 2022 11:49:21 +0200 Subject: [PATCH 014/124] software node: Switch property entry test to a new API Switch property entry test to use software_node_register_node_group() API. The current one is going to be removed soon. Signed-off-by: Andy Shevchenko Acked-by: Greg Kroah-Hartman Acked-by: Sakari Ailus Tested-by: Daniel Scally Acked-by: Heikki Krogerus Link: https://lore.kernel.org/r/20221228094922.84119-4-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/test/property-entry-test.c | 30 ++++++++++++------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/base/test/property-entry-test.c b/drivers/base/test/property-entry-test.c index 6071d5bc128c2d..dd2b606d76a3f5 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[] = { From 3dbdd92014a410778de8406e9e3253e353f51c2b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Dec 2022 11:49:22 +0200 Subject: [PATCH 015/124] software node: Remove unused APIs There are no more users of software_node_register_nodes() and software_node_unregister_nodes(). Remove them. Signed-off-by: Andy Shevchenko Acked-by: Greg Kroah-Hartman Acked-by: Sakari Ailus Tested-by: Daniel Scally Acked-by: Heikki Krogerus Link: https://lore.kernel.org/r/20221228094922.84119-5-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/swnode.c | 61 ---------------------------------------- include/linux/property.h | 3 -- 2 files changed, 64 deletions(-) diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index 0a482212c7e8ea..da3c1c2cb9a808 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -819,67 +819,6 @@ swnode_register(const struct software_node *node, struct swnode *parent, return &swnode->fwnode; } -/** - * 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/include/linux/property.h b/include/linux/property.h index 37179e3abad5c5..1ffd4f9bb67b23 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -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); From 64f797423379a333e3ba5373ee01353d7029727e Mon Sep 17 00:00:00 2001 From: Umang Jain Date: Tue, 20 Dec 2022 14:21:16 +0530 Subject: [PATCH 016/124] platform: Document platform_add_devices() return value platform_add_devices() returns 0 on success and negative errno on failure. Document it. Signed-off-by: Umang Jain Link: https://lore.kernel.org/r/20221220085116.19837-1-umang.jain@ideasonboard.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index a4938d1c8fe1d3..d6690d7053140d 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -499,6 +499,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) { From 16227e4bc67c647d370231803b375364ee2d9e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Dec 2022 23:13:15 +0100 Subject: [PATCH 017/124] staging: greybus: codecs: Drop empty platform remove function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A remove callback just returning 0 is equivalent to no remove callback at all. So drop the useless function. Signed-off-by: Uwe Kleine-König Reviewed-by: Alex Elder Reviewed-by: Johan Hovold Link: https://lore.kernel.org/r/20221212221315.3778788-1-u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_codec.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 0ad8aeabccbfdd..72ace74ea605d7 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); From d16ee771fbece55e4a1fd5e032eeebee1efacc1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 12 Dec 2022 22:20:37 +0100 Subject: [PATCH 018/124] serial: arc_uart: Drop empty platform remove function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A remove callback just returning 0 is equivalent to no remove callback at all. So drop the useless function. Signed-off-by: Uwe Kleine-König Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20221212212037.3773636-1-u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/arc_uart.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 748e8b1cf4f7f3..59e25f2b663221 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, From 9dd4541b1693e9aa124a167b40e294aa6906433f Mon Sep 17 00:00:00 2001 From: Soha Jin Date: Fri, 11 Nov 2022 17:45:42 +0800 Subject: [PATCH 019/124] platform: remove useless if-branch in __platform_get_irq_byname() When CONFIG_OF_IRQ is not enabled, there will be a stub method that always returns 0 when getting IRQ. Thus, the if-branch can be removed safely. Signed-off-by: Soha Jin Link: https://lore.kernel.org/r/20221111094542.270540-1-soha@lohu.info Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d6690d7053140d..b10a130cd43341 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) { From c3719bd9eeb2edf84bd263d662e36ca0ba262a23 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Wed, 4 Jan 2023 19:30:24 +0100 Subject: [PATCH 020/124] cacheinfo: Use RISC-V's init_cache_level() as generic OF implementation RISC-V's implementation of init_of_cache_level() is following the Devicetree Specification v0.3 regarding caches, cf.: - s3.7.3 'Internal (L1) Cache Properties' - s3.8 'Multi-level and Shared Cache Nodes' Allow reusing the implementation by moving it. Also make 'levels', 'leaves' and 'level' unsigned int. Signed-off-by: Pierre Gondois Reviewed-by: Conor Dooley Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-2-pierre.gondois@arm.com Signed-off-by: Sudeep Holla --- arch/riscv/kernel/cacheinfo.c | 39 +------------------------------ drivers/base/cacheinfo.c | 44 +++++++++++++++++++++++++++++++++++ include/linux/cacheinfo.h | 1 + 3 files changed, 46 insertions(+), 38 deletions(-) diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index 90deabfe63eaac..440a3df5944cf5 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -115,44 +115,7 @@ 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; + return init_of_cache_level(cpu); } int populate_cache_leaves(unsigned int cpu) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 950b22cdb5f7cd..b60788aacfefc5 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -229,8 +229,52 @@ static int cache_setup_of_node(unsigned int cpu) return 0; } + +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 = 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; +} + #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) diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 00b7a6ae861758..ff0328f3fbb0f8 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -80,6 +80,7 @@ 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); From 8844c3df001bc1d8397fddea341308da63855d53 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Wed, 4 Jan 2023 19:30:25 +0100 Subject: [PATCH 021/124] cacheinfo: Return error code in init_of_cache_level() Make init_of_cache_level() return an error code when the cache information parsing fails to help detecting missing information. init_of_cache_level() is only called for riscv. Returning an error code instead of 0 will prevent detect_cache_attributes() to allocate memory if an incomplete DT is parsed. Signed-off-by: Pierre Gondois Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-3-pierre.gondois@arm.com Signed-off-by: Sudeep Holla --- drivers/base/cacheinfo.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index b60788aacfefc5..0a96d0b9338aba 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -251,11 +251,11 @@ int init_of_cache_level(unsigned int cpu) of_node_put(prev); prev = np; if (!of_device_is_compatible(np, "cache")) - break; + goto err_out; if (of_property_read_u32(np, "cache-level", &level)) - break; + goto err_out; if (level <= levels) - break; + goto err_out; if (of_property_read_bool(np, "cache-size")) ++leaves; if (of_property_read_bool(np, "i-cache-size")) @@ -270,6 +270,10 @@ int init_of_cache_level(unsigned int cpu) this_cpu_ci->num_leaves = leaves; return 0; + +err_out: + of_node_put(np); + return -EINVAL; } #else From 504450d05c545a839b22542c72ddc388740462ac Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 10:23:30 +0100 Subject: [PATCH 022/124] driver core: bus.h: document bus notifiers better The bus notifier values are not documented all that well, so clean this up and make a real enumerated type for them and document them much better. When doing this, remove the hex values and just rely on the enumerated type instead as that is all that is needed. Reviewed-by: Randy Dunlap Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230111092331.3946745-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- include/linux/device/bus.h | 42 +++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index d529f644e92b07..7b4a48b5159b62 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -257,21 +257,35 @@ extern int bus_register_notifier(struct bus_type *bus, extern int bus_unregister_notifier(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); From ed9f918174cb35ba51d2fc86a613305dd8bc4cfe Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 10:23:31 +0100 Subject: [PATCH 023/124] driver core: bus: move bus notifier logic into bus.c The logic to touch the bus notifier was open-coded in numberous places in the driver core. Clean that up by creating a local bus_notify() function and have everyone call this function instead, making the reading of the caller code simpler and easier to maintain over time. Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230111092331.3946745-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 1 + drivers/base/bus.c | 8 ++++++++ drivers/base/core.c | 13 +++---------- drivers/base/dd.c | 28 +++++++--------------------- 4 files changed, 19 insertions(+), 31 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 2eb722d89f1064..3d1da1027206be 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -130,6 +130,7 @@ 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); extern int bus_add_driver(struct device_driver *drv); extern void bus_remove_driver(struct device_driver *drv); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 428c26c6b615e1..cf1b8f00b4c0c7 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -850,6 +850,14 @@ int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb) } EXPORT_SYMBOL_GPL(bus_unregister_notifier); +void bus_notify(struct device *dev, enum bus_notifier_event value) +{ + struct bus_type *bus = dev->bus; + + if (bus) + blocking_notifier_call_chain(&bus->p->bus_notifier, value, dev); +} + struct kset *bus_get_kset(struct bus_type *bus) { return &bus->p->subsys; diff --git a/drivers/base/core.c b/drivers/base/core.c index 506289e6b04dd1..110dbd4fb57011 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3453,10 +3453,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); /* @@ -3637,9 +3634,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) @@ -3670,9 +3665,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); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 69daf9d414ebe1..817ef27a78f7eb 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -411,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); } @@ -433,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)); @@ -500,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); @@ -693,9 +687,7 @@ static int really_probe(struct device *dev, struct device_driver *drv) 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: @@ -1241,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); @@ -1258,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); } } From de0df442ee49cb1f6ee58f3fec5dcb5e5eb70aab Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Wed, 4 Jan 2023 19:30:26 +0100 Subject: [PATCH 024/124] cacheinfo: Check 'cache-unified' property to count cache leaves The DeviceTree Specification v0.3 specifies that the cache node '[d-|i-|]cache-size' property is required. The 'cache-unified' property is specifies whether the cache level is separate or unified. If the cache-size property is missing, no cache leaves is accounted. This can lead to a 'BUG: KASAN: slab-out-of-bounds' [1] bug. Check 'cache-unified' property and always account for at least one cache leaf when parsing the device tree. [1] https://lore.kernel.org/all/0f19cb3f-d6cf-4032-66d2-dedc9d09a0e3@linaro.org/ Reported-by: Krzysztof Kozlowski Signed-off-by: Pierre Gondois Tested-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230104183033.755668-4-pierre.gondois@arm.com Signed-off-by: Sudeep Holla --- drivers/base/cacheinfo.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 0a96d0b9338aba..9ad4403f2dabd4 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -230,12 +230,9 @@ static int cache_setup_of_node(unsigned int cpu) return 0; } -int init_of_cache_level(unsigned int cpu) +static int of_count_cache_leaves(struct device_node *np) { - 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 = 0, level; + unsigned int leaves = 0; if (of_property_read_bool(np, "cache-size")) ++leaves; @@ -243,6 +240,28 @@ int init_of_cache_level(unsigned int cpu) ++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; @@ -256,12 +275,8 @@ int init_of_cache_level(unsigned int cpu) goto err_out; if (level <= levels) goto err_out; - 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; + + leaves += of_count_cache_leaves(np); levels = level; } From fa4d566a605bc4cf32d69f16ef8cf9696635f75a Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Wed, 4 Jan 2023 19:30:27 +0100 Subject: [PATCH 025/124] ACPI: PPTT: Remove acpi_find_cache_levels() acpi_find_cache_levels() is used at a single place and is short enough to be merged into the calling function. The removal allows an easier renaming of the calling function in the next patch. Also reorder the local variables in the 'reversed Christmas tree' order. Signed-off-by: Pierre Gondois Reviewed-by: Jeremy Linton Acked-by: Rafael J. Wysocki Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-5-pierre.gondois@arm.com Signed-off-by: Sudeep Holla --- drivers/acpi/pptt.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index c91342dcbcd636..97c1d33822d1e8 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -281,19 +281,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) { @@ -613,9 +600,10 @@ static int check_acpi_cpu_flag(unsigned int cpu, int rev, u32 flag) */ int acpi_find_last_cache_level(unsigned int cpu) { - u32 acpi_cpu_id; + struct acpi_pptt_processor *cpu_node; struct acpi_table_header *table; int number_of_levels = 0; + u32 acpi_cpu_id; table = acpi_get_pptt(); if (!table) @@ -624,7 +612,10 @@ int acpi_find_last_cache_level(unsigned int cpu) pr_debug("Cache Setup find last level CPU=%d\n", cpu); acpi_cpu_id = get_acpi_id_for_cpu(cpu); - number_of_levels = acpi_find_cache_levels(table, acpi_cpu_id); + cpu_node = acpi_find_processor_node(table, acpi_cpu_id); + if (cpu_node) + number_of_levels = acpi_count_levels(table, cpu_node); + pr_debug("Cache Setup find last level level=%d\n", number_of_levels); return number_of_levels; From bd500361a937c03a3da57178287ce543c8f3681b Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Wed, 4 Jan 2023 19:30:28 +0100 Subject: [PATCH 026/124] ACPI: PPTT: Update acpi_find_last_cache_level() to acpi_get_cache_info() acpi_find_last_cache_level() allows to find the last level of cache for a given CPU. The function is only called on arm64 ACPI based platforms to check for cache information that would be missing in the CLIDR_EL1 register. To allow populating (struct cpu_cacheinfo).num_leaves by only parsing a PPTT, update acpi_find_last_cache_level() to get the 'split_levels', i.e. the number of cache levels being split in data/instruction caches. It is assumed that there will not be data/instruction caches above a unified cache. If a split level consist of one data cache and no instruction cache (or opposite), then the missing cache will still be populated by default with minimal cache information, and maximal cpumask (all non-existing caches have the same fw_token). Suggested-by: Jeremy Linton Signed-off-by: Pierre Gondois Reviewed-by: Jeremy Linton Acked-by: Rafael J. Wysocki Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-6-pierre.gondois@arm.com Signed-off-by: Sudeep Holla --- arch/arm64/kernel/cacheinfo.c | 11 +++-- drivers/acpi/pptt.c | 76 +++++++++++++++++++++++------------ include/linux/cacheinfo.h | 9 +++-- 3 files changed, 63 insertions(+), 33 deletions(-) diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c index 97c42be71338a9..36c3b07cdf2d13 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,10 +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); + } else { + ret = acpi_get_cache_info(cpu, &fw_level, NULL); + if (ret < 0) + return ret; + } if (fw_level < 0) return fw_level; diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index 97c1d33822d1e8..10975bb603fb15 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; } /** @@ -321,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); } @@ -589,36 +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) { 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); cpu_node = acpi_find_processor_node(table, acpi_cpu_id); - if (cpu_node) - number_of_levels = acpi_count_levels(table, cpu_node); + if (!cpu_node) + return -ENOENT; - pr_debug("Cache Setup find last level level=%d\n", number_of_levels); + 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/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index ff0328f3fbb0f8..00d8e7f9d1c6e4 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -88,19 +88,22 @@ bool last_level_cache_is_shared(unsigned int cpu_x, unsigned int cpu_y); 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; } #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); From 5944ce092b97caed5d86d961e963b883b5c44ee2 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Wed, 4 Jan 2023 19:30:29 +0100 Subject: [PATCH 027/124] arch_topology: Build cacheinfo from primary CPU commit 3fcbf1c77d08 ("arch_topology: Fix cache attributes detection in the CPU hotplug path") adds a call to detect_cache_attributes() to populate the cacheinfo before updating the siblings mask. detect_cache_attributes() allocates memory and can take the PPTT mutex (on ACPI platforms). On PREEMPT_RT kernels, on secondary CPUs, this triggers a: 'BUG: sleeping function called from invalid context' [1] as the code is executed with preemption and interrupts disabled. The primary CPU was previously storing the cache information using the now removed (struct cpu_topology).llc_id: commit 5b8dc787ce4a ("arch_topology: Drop LLC identifier stash from the CPU topology") allocate_cache_info() tries to build the cacheinfo from the primary CPU prior secondary CPUs boot, if the DT/ACPI description contains cache information. If allocate_cache_info() fails, then fallback to the current state for the cacheinfo allocation. [1] will be triggered in such case. When unplugging a CPU, the cacheinfo memory cannot be freed. If it was, then the memory would be allocated early by the re-plugged CPU and would trigger [1]. Note that populate_cache_leaves() might be called multiple times due to populate_leaves being moved up. This is required since detect_cache_attributes() might be called with per_cpu_cacheinfo(cpu) being allocated but not populated. [1]: | BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:46 | in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 0, name: swapper/111 | preempt_count: 1, expected: 0 | RCU nest depth: 1, expected: 1 | 3 locks held by swapper/111/0: | #0: (&pcp->lock){+.+.}-{3:3}, at: get_page_from_freelist+0x218/0x12c8 | #1: (rcu_read_lock){....}-{1:3}, at: rt_spin_trylock+0x48/0xf0 | #2: (&zone->lock){+.+.}-{3:3}, at: rmqueue_bulk+0x64/0xa80 | irq event stamp: 0 | hardirqs last enabled at (0): 0x0 | hardirqs last disabled at (0): copy_process+0x5dc/0x1ab8 | softirqs last enabled at (0): copy_process+0x5dc/0x1ab8 | softirqs last disabled at (0): 0x0 | Preemption disabled at: | migrate_enable+0x30/0x130 | CPU: 111 PID: 0 Comm: swapper/111 Tainted: G W 6.0.0-rc4-rt6-[...] | Call trace: | __kmalloc+0xbc/0x1e8 | detect_cache_attributes+0x2d4/0x5f0 | update_siblings_masks+0x30/0x368 | store_cpu_topology+0x78/0xb8 | secondary_start_kernel+0xd0/0x198 | __secondary_switched+0xb0/0xb4 Signed-off-by: Pierre Gondois Reviewed-by: Sudeep Holla Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20230104183033.755668-7-pierre.gondois@arm.com Signed-off-by: Sudeep Holla --- arch/riscv/kernel/cacheinfo.c | 5 --- drivers/base/arch_topology.c | 12 +++++- drivers/base/cacheinfo.c | 71 ++++++++++++++++++++++++++--------- include/linux/cacheinfo.h | 1 + 4 files changed, 65 insertions(+), 24 deletions(-) diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index 440a3df5944cf5..3a13113f1b29ad 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -113,11 +113,6 @@ static void fill_cacheinfo(struct cacheinfo **this_leaf, } } -int init_cache_level(unsigned int cpu) -{ - return init_of_cache_level(cpu); -} - int populate_cache_leaves(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index e7d6e6657ffa04..b1c1dd38ab011a 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/cacheinfo.c b/drivers/base/cacheinfo.c index 9ad4403f2dabd4..c9bcecf76c7f51 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -389,10 +389,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) @@ -405,29 +401,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, split_levels; + 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. @@ -436,7 +474,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/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 00d8e7f9d1c6e4..dfef57077cd089 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -85,6 +85,7 @@ 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 /* From 198102c9103fc78d8478495971947af77edb05c1 Mon Sep 17 00:00:00 2001 From: Yong-Xuan Wang Date: Tue, 17 Jan 2023 10:51:33 +0000 Subject: [PATCH 028/124] cacheinfo: Fix shared_cpu_map to handle shared caches at different levels The cacheinfo sets up the shared_cpu_map by checking whether the caches with the same index are shared between CPUs. However, this will trigger slab-out-of-bounds access if the CPUs do not have the same cache hierarchy. Another problem is the mismatched shared_cpu_map when the shared cache does not have the same index between CPUs. CPU0 I D L3 index 0 1 2 x ^ ^ ^ ^ index 0 1 2 3 CPU1 I D L2 L3 This patch checks each cache is shared with all caches on other CPUs. Reviewed-by: Pierre Gondois Signed-off-by: Yong-Xuan Wang Link: https://lore.kernel.org/r/20230117105133.4445-2-yongxuan.wang@sifive.com Signed-off-by: Sudeep Holla --- drivers/base/cacheinfo.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index c9bcecf76c7f51..418a18acc8f9e0 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -319,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) @@ -347,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 */ @@ -365,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); @@ -376,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; + } + } } } } From 52af7863508e94f3e05e43a3f2f3943a71dcffab Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 17 Jan 2023 17:21:20 +0200 Subject: [PATCH 029/124] device property: Make fwnode_graph_for_each_endpoint() consistent Make fwnode_graph_for_each_endpoint() consistent with the rest of for_each_*() definitions in the file, i.e. use the form of for (iter = func(NULL); iter; \ iter = func(iter)) as it's done in all the rest of the similar macro definitions. Signed-off-by: Andy Shevchenko Acked-by: Rafael J. Wysocki Acked-by: Sakari Ailus Acked-by: Heikki Krogerus Link: https://lore.kernel.org/r/20230117152120.42531-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- include/linux/property.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/property.h b/include/linux/property.h index 1ffd4f9bb67b23..0a29db15ff345d 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); From 95b2a034784658c4512db846918475d4954901d6 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Sat, 26 Nov 2022 19:16:34 +0800 Subject: [PATCH 030/124] kernfs: remove an unused if statement in kernfs_path_from_node_locked() It makes no sense to call kernfs_path_from_node_locked() with NULL buf, and no one is doing that right now. Suggested-by: Tejun Heo Signed-off-by: Zhen Lei Acked-by: Tejun Heo Link: https://lore.kernel.org/r/20221126111634.1994-1-thunder.leizhen@huawei.com Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/dir.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 935ef8cb02b26b..7b13b1c3424c7a 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; From 1ad5288f2bd37818fc90b77635611110c44df104 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 2 Jan 2023 13:15:54 -0800 Subject: [PATCH 031/124] test_firmware: use kernel-doc struct notation Add "struct" to the kernel-doc notation to prevent a warning: lib/test_firmware.c:98: warning: cannot understand function prototype: 'struct test_config ' Signed-off-by: Randy Dunlap Cc: Luis Chamberlain Cc: Russ Weight Cc: Kees Cook Cc: Greg Kroah-Hartman Acked-by: Luis Chamberlain Link: https://lore.kernel.org/r/20230102211554.25629-1-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- lib/test_firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/test_firmware.c b/lib/test_firmware.c index e207bc08820d0e..6d7becc7e5d5fb 100644 --- a/lib/test_firmware.c +++ b/lib/test_firmware.c @@ -50,7 +50,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 From f7d85515bd21902b218370a1a6301f76e4e636ff Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 14 Jan 2023 10:22:03 +0100 Subject: [PATCH 032/124] test_firmware: Use kstrtobool() instead of strtobool() strtobool() is the same as kstrtobool(). However, the latter is more used within the kernel. In order to remove strtobool() and slightly simplify kstrtox.h, switch to the other function name. While at it, include the corresponding header file () Signed-off-by: Christophe JAILLET Acked-by: Luis Chamberlain Link: https://lore.kernel.org/r/34f04735d20e0138695dd4070651bd860a36b81c.1673688120.git.christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- lib/test_firmware.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/test_firmware.c b/lib/test_firmware.c index 6d7becc7e5d5fb..05ed84c2fc4cec 100644 --- a/lib/test_firmware.c +++ b/lib/test_firmware.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -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; From 7c09f4281cb6ec0fc202f53924ed6c389c61bf0e Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 20 Jan 2023 13:57:26 +0800 Subject: [PATCH 033/124] drivers/base/memory: Fix comments for phys_index_show() According to 'admin-guide/mm/memory-hotplug.rst', the memory block ID, instead of the section index, is shown by '/sys/devices/system/memory/ memoryX/phys_index'. Fix the comments to match with 'admin-guide/mm/memory-hotplug.rst'. Besides, use the existing helper memory_block_id() to convert the section index to the memory block index. No functional change intended. Signed-off-by: Gavin Shan Link: https://lore.kernel.org/r/20230120055727.355483-2-gshan@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/memory.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index fe98fb8d94e51c..b456ac21361058 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)); } /* From 6977b1a5d67097eaa4d02b0c126c04cc6e8917c0 Mon Sep 17 00:00:00 2001 From: Zhengchao Shao Date: Wed, 23 Nov 2022 09:20:42 +0800 Subject: [PATCH 034/124] driver core: fix resource leak in device_add() When calling kobject_add() failed in device_add(), it will call cleanup_glue_dir() to free resource. But in kobject_add(), dev->kobj.parent has been set to NULL. This will cause resource leak. The process is as follows: device_add() get_device_parent() class_dir_create_and_add() kobject_add() //kobject_get() ... dev->kobj.parent = kobj; ... kobject_add() //failed, but set dev->kobj.parent = NULL ... glue_dir = get_glue_dir(dev) //glue_dir = NULL, and goto //"Error" label ... cleanup_glue_dir() //becaues glue_dir is NULL, not call //kobject_put() The preceding problem may cause insmod mac80211_hwsim.ko to failed. sysfs: cannot create duplicate filename '/devices/virtual/mac80211_hwsim' Call Trace: dump_stack_lvl+0x8e/0xd1 sysfs_warn_dup.cold+0x1c/0x29 sysfs_create_dir_ns+0x224/0x280 kobject_add_internal+0x2aa/0x880 kobject_add+0x135/0x1a0 get_device_parent+0x3d7/0x590 device_add+0x2aa/0x1cb0 device_create_groups_vargs+0x1eb/0x260 device_create+0xdc/0x110 mac80211_hwsim_new_radio+0x31e/0x4790 [mac80211_hwsim] init_mac80211_hwsim+0x48d/0x1000 [mac80211_hwsim] do_one_initcall+0x10f/0x630 do_init_module+0x19f/0x5e0 load_module+0x64b7/0x6eb0 __do_sys_finit_module+0x140/0x200 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 kobject_add_internal failed for mac80211_hwsim with -EEXIST, don't try to register things with the same name in the same directory. Fixes: cebf8fd16900 ("driver core: fix race between creating/querying glue dir and its cleanup") Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20221123012042.335252-1-shaozhengchao@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 110dbd4fb57011..39dbd532cfb3e4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3413,7 +3413,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; } From 0d150f967e8410e1e6712484543eec709356a65d Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Tue, 22 Nov 2022 15:37:28 +0800 Subject: [PATCH 035/124] driver core: location: Free struct acpi_pld_info *pld before return false struct acpi_pld_info *pld should be freed before the return of allocation failure, to prevent memory leak, add the ACPI_FREE() to fix it. Fixes: bc443c31def5 ("driver core: location: Check for allocations failure") Signed-off-by: Hanjun Guo Link: https://lore.kernel.org/r/1669102648-11517-1-git-send-email-guohanjun@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/physical_location.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/base/physical_location.c b/drivers/base/physical_location.c index 87af641cfe1a3d..951819e71b4ad4 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; From a86367803838b369fe5486ac18771d14723c258c Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Thu, 10 Nov 2022 18:23:07 +0800 Subject: [PATCH 036/124] drivers: base: transport_class: fix possible memory leak Current some drivers(like iscsi) call transport_register_device() failed, they don't call transport_destroy_device() to release the memory allocated in transport_setup_device(), because they don't know what was done, it should be internal thing to release the resource in register function. So fix this leak by calling destroy function inside register function. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221110102307.3492557-1-yangyingliang@huawei.com Signed-off-by: Greg Kroah-Hartman --- include/linux/transport_class.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h index 63076fb835e342..2efc271a96fa6b 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 From e5da06b27ff5a148e42265c8e306670a9d913969 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 15 Nov 2022 11:16:38 +0800 Subject: [PATCH 037/124] drivers: base: transport_class: fix resource leak when transport_add_device() fails The normal call sequence of using transport class is: Add path: transport_setup_device() transport_setup_classdev() // call sas_host_setup() here transport_add_device() // if fails, need call transport_destroy_device() transport_configure_device() Remove path: transport_remove_device() transport_remove_classdev // call sas_host_remove() here transport_destroy_device() If transport_add_device() fails, need call transport_destroy_device() to free memory, but in this case, ->remove() is not called, and the resources allocated in ->setup() are leaked. So fix these leaks by calling ->remove() in transport_add_class_device() if it returns error. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221115031638.3816551-1-yangyingliang@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/transport_class.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c index ccc86206e5087f..09ee2a1e35bbd3 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; } From 00142bfd5a916a0b3899cc709bf8f5042cf3d084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 21 Dec 2022 16:17:52 +0000 Subject: [PATCH 038/124] kernels/ksysfs.c: export kernel address bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This can be used by userspace to determine the address size of the running kernel. It frees userspace from having to interpret this information from the UTS machine field. Userspace implementation: https://github.com/util-linux/util-linux/pull/1966 Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20221221-address-bits-v1-1-8446b13244ac@weissschuh.net Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-kernel-address_bits | 10 ++++++++++ kernel/ksysfs.c | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-kernel-address_bits diff --git a/Documentation/ABI/testing/sysfs-kernel-address_bits b/Documentation/ABI/testing/sysfs-kernel-address_bits new file mode 100644 index 00000000000000..5d09ff84d4d6e2 --- /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 +Description: + The address size of the running kernel in bits. + + Access: Read + +Users: util-linux diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 2df00b789b907c..0408aab80941b6 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 From 0b2a1a3938aad80fb19cb53cbbd4679eeb37e3a8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 20 Jan 2023 20:46:57 +0100 Subject: [PATCH 039/124] driver core: class: Clear private pointer on registration failures Clear the class private pointer if __class_register() fails for it, so as to allow its users to verify that the class is usable by checking the value of that pointer. For consistency, clear that pointer before freeing the object pointed to by it in class_release(). Signed-off-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/4463268.LvFx2qVVIh@kreacher Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/base/class.c b/drivers/base/class.c index 3366da9c3ff6eb..a38b0d7d681d70 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 @@ -186,17 +188,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); From 8e3938a5d2d89d8a4b9688ba9cbec500640d401d Mon Sep 17 00:00:00 2001 From: Luis Chamberlain Date: Mon, 23 Jan 2023 13:52:55 -0800 Subject: [PATCH 040/124] docs: embargoed-hardware-issues: add embargoed HW contact for Samsung MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After discussions internally at the company, Javier has been volunteered and is willing to be the embargoed hardware contact for Samsung. Cc: Javier González Signed-off-by: Luis Chamberlain Acked-by: Javier González Link: https://lore.kernel.org/r/20230123215255.381312-1-mcgrof@kernel.org Signed-off-by: Greg Kroah-Hartman --- Documentation/process/embargoed-hardware-issues.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst index b6b4481e2474f3..df978127f2d785 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 Intel Tony Luck Qualcomm Trilok Soni + Samsung Javier González Microsoft James Morris VMware From a77ad4bf792652340ab334956e69b46ec2fdaefb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:03 +0100 Subject: [PATCH 041/124] of: device: make of_device_uevent_modalias() take a const device * of_device_uevent_modalias() does not modify the device pointer passed to it, so mark it constant. In order to properly do this, a number of busses need to have a modalias function added as they were attempting to just point to of_device_uevent_modalias instead of their bus-specific modalias function. This is fine except if the prototype for a bus and device type modalias function diverges and then problems could happen. To prevent all of that, just wrap the call to of_device_uevent_modalias() directly for each bus and device type individually. Cc: Michael Ellerman Cc: Nicholas Piggin Cc: Christophe Leroy Cc: Chen-Yu Tsai Cc: Jernej Skrabec Cc: Samuel Holland Cc: David Airlie Cc: Daniel Vetter Cc: Benjamin Herrenschmidt Cc: Rob Herring Cc: Frank Rowand Cc: Liang He Cc: Thomas Gleixner Cc: Christophe JAILLET Cc: Thomas Zimmermann Cc: Dmitry Baryshkov Cc: Douglas Anderson Cc: Lyude Paul Cc: Corentin Labbe Cc: Zou Wei Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-sunxi@lists.linux.dev Cc: dri-devel@lists.freedesktop.org Cc: devicetree@vger.kernel.org Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/platforms/pseries/ibmebus.c | 7 ++++++- drivers/bus/sunxi-rsb.c | 7 ++++++- drivers/gpu/drm/display/drm_dp_aux_bus.c | 7 ++++++- drivers/macintosh/macio_asic.c | 7 ++++++- drivers/of/device.c | 4 ++-- include/linux/of_device.h | 4 ++-- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c index a870cada7acd23..58b798a0e87984 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(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/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 3aa91aed3bf733..a180af11e03432 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(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/gpu/drm/display/drm_dp_aux_bus.c b/drivers/gpu/drm/display/drm_dp_aux_bus.c index f5741b45ca077f..e31a0261c53e52 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(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/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 3bc1f374e65770..7f2b0107c73359 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(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/of/device.c b/drivers/of/device.c index c674a13c305587..dda51b7ce5970d 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/include/linux/of_device.h b/include/linux/of_device.h index ab7d557d541d5c..f4b57614979de8 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; From fa838c8ce53714eba788ea877520788bc72c27bd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:04 +0100 Subject: [PATCH 042/124] i3c: move dev_to_i3cdev() to use container_of_const() The driver core is changing to pass some pointers as const, so move dev_to_i3cdev() to use container_of_const() to handle this change. dev_to_i3cdev() now properly keeps the const-ness of the pointer passed into it, while as before it could be lost. Acked-by: Alexandre Belloni Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-3-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/i3c/device.c | 12 ------------ include/linux/i3c/device.h | 9 ++++++++- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c index 9762630b917ea5..d111499061b285 100644 --- a/drivers/i3c/device.c +++ b/drivers/i3c/device.c @@ -208,18 +208,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 diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h index 1c997abe868c60..68b558929aeca2 100644 --- a/include/linux/i3c/device.h +++ b/include/linux/i3c/device.h @@ -186,7 +186,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, From 34be683add6ccdbc9d589b79077ea7f48ff7ee0c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:05 +0100 Subject: [PATCH 043/124] platform/surface: aggregator: move to_ssam_device() to use container_of_const() The driver core is changing to pass some pointers as const, so move to_ssam_device() to use container_of_const() to handle this change. to_ssam_device() now properly keeps the const-ness of the pointer passed into it, while as before it could be lost. Reviewed-by: Maximilian Luz Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-4-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- include/linux/surface_aggregator/device.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h index 46c45d1b63682e..24151a0e2c96e3 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 From 49b7fc1c25481c823e391b5617546b1ad4af0852 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:06 +0100 Subject: [PATCH 044/124] firewire: move fw_device() and fw_unit() to use container_of_const() The driver core is changing to pass some pointers as const, so move fw_device() and fw_unit() functions to use container_of_const() to handle this change. fw_device() and fw_unit() now properly keeps the const-ness of the pointer passed into it, while as before it could be lost. This also required turning fw_parent_device() into a macro to preserve the const-ness of the pointer passed into it if necessary. Cc: Stefan Richter Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-5-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- include/linux/firewire.h | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 980019053e541a..03ac31ada5e60d 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; From 162736b0d71a9630f7c99dda7cefd5600fa03d69 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:07 +0100 Subject: [PATCH 045/124] driver core: make struct device_type.uevent() take a const * The uevent() callback in struct device_type should not be modifying the device that is passed into it, so mark it as a const * and propagate the function signature changes out into all relevant subsystems that use this callback. Cc: Alan Stern Cc: Andreas Noever Cc: Andy Shevchenko Cc: Bard Liao Cc: Chaitanya Kulkarni Cc: Dan Williams Cc: Dmitry Torokhov Cc: Frank Rowand Cc: Ira Weiny Cc: Jason Gunthorpe Cc: Jens Axboe Cc: Jilin Yuan Cc: Jiri Slaby Cc: Len Brown Cc: Mark Gross Cc: "Martin K. Petersen" Cc: "Matthew Wilcox (Oracle)" Cc: Maximilian Luz Cc: Michael Jamet Cc: Ming Lei Cc: Pierre-Louis Bossart Cc: Rob Herring Cc: Sakari Ailus Cc: Sanyog Kale Cc: Sean Young Cc: Stefan Richter Cc: Thomas Gleixner Cc: Won Chung Cc: Yehezkel Bernat Acked-by: Rafael J. Wysocki Acked-by: Mika Westerberg # for Thunderbolt Acked-by: Mauro Carvalho Chehab Acked-by: Alexandre Belloni Acked-by: Heikki Krogerus Acked-by: Wolfram Sang Acked-by: Vinod Koul Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-6-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- block/partitions/core.c | 4 ++-- drivers/acpi/device_sysfs.c | 8 ++++---- drivers/acpi/internal.h | 2 +- drivers/firewire/core-device.c | 8 ++++---- drivers/gpu/drm/display/drm_dp_aux_bus.c | 2 +- drivers/i2c/i2c-core-base.c | 4 ++-- drivers/i3c/device.c | 2 +- drivers/i3c/master.c | 4 ++-- drivers/input/input.c | 16 ++++++++-------- drivers/media/rc/rc-main.c | 2 +- drivers/platform/surface/aggregator/bus.c | 4 ++-- drivers/soundwire/bus_type.c | 4 ++-- drivers/thunderbolt/switch.c | 4 ++-- drivers/thunderbolt/tb.h | 2 +- drivers/thunderbolt/xdomain.c | 6 +++--- drivers/tty/serdev/core.c | 2 +- drivers/usb/core/message.c | 8 ++++---- drivers/usb/core/usb.c | 4 ++-- drivers/usb/phy/phy.c | 6 +++--- drivers/usb/roles/class.c | 3 +-- drivers/usb/typec/class.c | 2 +- include/linux/acpi.h | 4 ++-- include/linux/device.h | 2 +- include/linux/i3c/device.h | 2 +- include/linux/soundwire/sdw_type.h | 2 +- 25 files changed, 53 insertions(+), 54 deletions(-) diff --git a/block/partitions/core.c b/block/partitions/core.c index b8112f52d38800..7b8ef6296abd03 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/device_sysfs.c b/drivers/acpi/device_sysfs.c index 120873dad2cc56..daff2c0c5c523e 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 ec584442fb2988..06ad497067acf8 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/firewire/core-device.c b/drivers/firewire/core-device.c index adddd8c45d0c1f..aa597cda0d8874 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/gpu/drm/display/drm_dp_aux_bus.c b/drivers/gpu/drm/display/drm_dp_aux_bus.c index e31a0261c53e52..8a165be1a82144 100644 --- a/drivers/gpu/drm/display/drm_dp_aux_bus.c +++ b/drivers/gpu/drm/display/drm_dp_aux_bus.c @@ -161,7 +161,7 @@ static void dp_aux_ep_dev_release(struct device *dev) kfree(aux_ep_with_data); } -static int dp_aux_ep_dev_modalias(struct device *dev, struct kobj_uevent_env *env) +static int dp_aux_ep_dev_modalias(const struct device *dev, struct kobj_uevent_env *env) { return of_device_uevent_modalias(dev, env); } diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 087e480b624cb2..51b78a52ab7fc1 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 d111499061b285..1a6a8703dbc3aa 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) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index d7e6f6c99aea55..7a60e1c5e58746 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 ca2e3dd7188bb9..0336e799d713ca 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/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 527d9324742bb3..6bdad6341844f5 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/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c index de539938896e25..407eb55050a6c8 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/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index 04b3529f892938..26c9a0a85d492d 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/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 363d712aa36434..cb6c304c445ee5 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2176,9 +2176,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 f9786976f5ecfc..909da0a98134e5 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -815,7 +815,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 3c51e47dd86b77..a48335c95d39be 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 0180e1e4e75df5..aa80de3a819478 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/usb/core/message.c b/drivers/usb/core/message.c index 127fac1af6767a..cc404bb7e8f776 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 11b15d7b357add..8527c06b65e656 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); diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index 1b24492bb4e5f6..4b468bde19cfb4 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 eacb46ec2ab303..56814ef80c24a5 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/class.c b/drivers/usb/typec/class.c index 5897905cb4f08b..a89d8fd3f46ca4 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -1737,7 +1737,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/include/linux/acpi.h b/include/linux/acpi.h index 5e6a876e17ba07..564b62f13bd0bc 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 *, @@ -958,7 +958,7 @@ static inline union acpi_object *acpi_evaluate_dsm(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/device.h b/include/linux/device.h index 44e3acae7b36e2..dad0614aad9643 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -88,7 +88,7 @@ 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); + int (*uevent)(const struct device *dev, struct kobj_uevent_env *env); char *(*devnode)(struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid); void (*release)(struct device *dev); diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h index 68b558929aeca2..ce115ef08fec2d 100644 --- a/include/linux/i3c/device.h +++ b/include/linux/i3c/device.h @@ -303,7 +303,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/soundwire/sdw_type.h b/include/linux/soundwire/sdw_type.h index 52eb66cd11bc96..d8c27f1e5559cb 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 From a9b12f8b4e3309c4c25d39e7ab818943b9c48c1c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:08 +0100 Subject: [PATCH 046/124] driver core: make struct device_type.devnode() take a const * The devnode() callback in struct device_type should not be modifying the device that is passed into it, so mark it as a const * and propagate the function signature changes out into all relevant subsystems that use this callback. Cc: Jens Axboe Cc: Alison Schofield Cc: Vishal Verma Cc: Ira Weiny Cc: Ben Widawsky Cc: Jeremy Kerr Cc: Joel Stanley Cc: Alistar Popple Cc: Eddie James Cc: Jonathan Cameron Cc: Jilin Yuan Cc: Heikki Krogerus Cc: Alan Stern Cc: Andy Shevchenko Cc: Thomas Gleixner Cc: Jason Gunthorpe Cc: "Rafael J. Wysocki" Cc: Won Chung Acked-by: Dan Williams Acked-by: Alexander Shishkin Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-7-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 2 +- drivers/cxl/core/memdev.c | 2 +- drivers/fsi/fsi-core.c | 6 +++--- drivers/hwtracing/intel_th/core.c | 6 +++--- drivers/hwtracing/intel_th/intel_th.h | 4 ++-- drivers/usb/core/usb.c | 4 ++-- include/linux/device.h | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 23cf83b3331cde..09f2ac548832aa 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1201,7 +1201,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/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index a74a93310d26d1..a38a0cc20d477b 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)); diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c index 694e80c06665df..0b927c9f4267b9 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/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index 7e753a75d23bba..cc7f879bb175d4 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 0ffb42990175ad..6cbba733f259a8 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/usb/core/usb.c b/drivers/usb/core/usb.c index 8527c06b65e656..4df26f4f76e604 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -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/include/linux/device.h b/include/linux/device.h index dad0614aad9643..318861000b8363 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -89,7 +89,7 @@ struct device_type { const char *name; const struct attribute_group **groups; int (*uevent)(const struct device *dev, struct kobj_uevent_env *env); - char *(*devnode)(struct device *dev, umode_t *mode, + char *(*devnode)(const struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid); void (*release)(struct device *dev); From 42bb5be8936f40a1d0e618766645e7fd0cbfe591 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:09 +0100 Subject: [PATCH 047/124] driver core: device_get_devnode() should take a const * device_get_devnode() should take a constant * to struct device as it does not modify it in any way, so modify the function definition to do this and move it out of device.h as it does not need to be exposed to the whole kernel tree. Cc: Thomas Gleixner Cc: Jason Gunthorpe Cc: Ira Weiny Cc: Dan Williams Cc: Won Chung Acked-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-8-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 2 ++ drivers/base/core.c | 2 +- include/linux/device.h | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 3d1da1027206be..2208af509ce874 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -159,6 +159,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/core.c b/drivers/base/core.c index 39dbd532cfb3e4..e39b6fa0eda6c8 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3733,7 +3733,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/include/linux/device.h b/include/linux/device.h index 318861000b8363..90aaf308c2594b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -907,8 +907,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) From b84d6d3b4580ad1551ada9046fbed85f3b1373af Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:10 +0100 Subject: [PATCH 048/124] vio: move to_vio_dev() to use container_of_const() The driver core is changing to pass some pointers as const, so move to_vio_dev() to use container_of_const() to handle this change. to_vio_dev() now properly keeps the const-ness of the pointer passed into it, while as before it could be lost. Cc: Michael Ellerman Cc: Nicholas Piggin Cc: Christophe Leroy Cc: "David S. Miller" Cc: "Gustavo A. R. Silva" Cc: Kees Cook Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-9-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/vio.h | 5 +---- arch/sparc/include/asm/vio.h | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/include/asm/vio.h b/arch/powerpc/include/asm/vio.h index e7479a4abf969e..cc9b787627adbc 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/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h index 2d7bdf665fd3b6..8a0c3c11c9ce49 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); From 2f89e23bc03e31b8e6f4994cdd954c0a7e35ca4a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:11 +0100 Subject: [PATCH 049/124] platform/x86: wmi: move dev_to_wblock() and dev_to_wdev to use container_of_const() The driver core is changing to pass some pointers as const, so move the dev_to_wdev() and dev_to_wblock() functions to use container_of_const() to handle this change. Both of these functions now properly keep the const-ness of the pointer passed into it, while as before it could be lost. Cc: Hans de Goede Cc: Mark Gross Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-10-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/wmi.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 5ffc00480aef6d..46d1edc08f20a4 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) { From 8afdae83e318f3cfb6eb1ee2ce289356936a663c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:12 +0100 Subject: [PATCH 050/124] drivers: hv: move device_to_hv_device to use container_of_const() The driver core is changing to pass some pointers as const, so move device_to_hv_device() to use container_of_const() to handle this change. device_to_hv_device() now properly keeps the const-ness of the pointer passed into it, while as before it could be lost. Cc: "K. Y. Srinivasan" Cc: Haiyang Zhang Cc: Dexuan Cui Acked-by: Wei Liu Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-11-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- include/linux/hyperv.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 85f7c5a63aa65f..8430e27f3c3fa7 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) { From af3011b6637cd7e94b2420455d41ba9e66c03aed Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:13 +0100 Subject: [PATCH 051/124] virtio: move dev_to_virtio() to use container_of_const() The driver core is changing to pass some pointers as const, so move dev_to_virtio() to use container_of_const() to handle this change. dev_to_virtio() now properly keeps the const-ness of the pointer passed into it, while as before it could be lost. Cc: "Michael S. Tsirkin" Cc: Jason Wang Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-12-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- include/linux/virtio.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/linux/virtio.h b/include/linux/virtio.h index dcab9c7e878433..2b472514c49b0a 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); From dad1b442840f690f39ce376ee0d1a1e67346983c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:14 +0100 Subject: [PATCH 052/124] drm/mipi-dsi: move to_mipi_dsi_device() to use container_of_const() The driver core is changing to pass some pointers as const, so move to_mipi_dsi_device() to use container_of_const() to handle this change. to_mipi_dsi_device() now properly keeps the const-ness of the pointer passed into it, while as before it could be lost. Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: David Airlie Cc: Daniel Vetter Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-13-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- include/drm/drm_mipi_dsi.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 20b21b577deaad..56a6557b2f4c14 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 From deaf8b21c803b3932071a7cf9b11f36e13000f5c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:15 +0100 Subject: [PATCH 053/124] mcb: move to_mcb_device() to use container_of_const() The driver core is changing to pass some pointers as const, so move to_mcb_device() to use container_of_const() to handle this change. to_mcb_device() now properly keeps the const-ness of the pointer passed into it, while as before it could be lost. Cc: Johannes Thumshirn Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-14-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- include/linux/mcb.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/linux/mcb.h b/include/linux/mcb.h index f6efb16f9d1b47..1e5893138afe02 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 From c6e8418521a8fd2068ade2c6a1514315c99cc717 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:16 +0100 Subject: [PATCH 054/124] xen/xenbus: move to_xenbus_device() to use container_of_const() The driver core is changing to pass some pointers as const, so move to_xenbus_device() to use container_of_const() to handle this change. to_xenbus_device() now properly keeps the const-ness of the pointer passed into it, while as before it could be lost. Cc: Stefano Stabellini Cc: Oleksandr Tyshchenko Cc: xen-devel@lists.xenproject.org Acked-by: Juergen Gross Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-15-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- include/xen/xenbus.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h index ad4fb4eab753d4..ef0505e72c2738 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 { From 2a81ada32f0e584fc0c943e0d3a8c9f4fae411d6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:17 +0100 Subject: [PATCH 055/124] driver core: make struct bus_type.uevent() take a const * The uevent() callback in struct bus_type should not be modifying the device that is passed into it, so mark it as a const * and propagate the function signature changes out into all relevant subsystems that use this callback. Acked-by: Rafael J. Wysocki Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-16-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- arch/mips/sgi-ip22/ip22-gio.c | 4 ++-- arch/parisc/kernel/drivers.c | 4 ++-- arch/powerpc/platforms/pseries/vio.c | 4 ++-- arch/sparc/kernel/vio.c | 2 +- drivers/acpi/bus.c | 2 +- drivers/amba/bus.c | 4 ++-- drivers/base/auxiliary.c | 2 +- drivers/base/cpu.c | 2 +- drivers/base/platform.c | 4 ++-- drivers/bcma/main.c | 6 +++--- drivers/bus/fsl-mc/fsl-mc-bus.c | 4 ++-- drivers/bus/mhi/ep/main.c | 4 ++-- drivers/bus/mhi/host/init.c | 4 ++-- drivers/bus/mips_cdmm.c | 4 ++-- drivers/bus/sunxi-rsb.c | 2 +- drivers/cxl/core/memdev.c | 2 +- drivers/cxl/core/port.c | 8 ++++---- drivers/cxl/cxl.h | 4 ++-- drivers/cxl/cxlmem.h | 2 +- drivers/dax/bus.c | 2 +- drivers/eisa/eisa-bus.c | 4 ++-- drivers/firmware/arm_ffa/bus.c | 4 ++-- drivers/fpga/dfl.c | 4 ++-- drivers/gpu/drm/drm_mipi_dsi.c | 4 ++-- drivers/gpu/host1x/bus.c | 2 +- drivers/greybus/core.c | 14 +++++++------- drivers/hid/hid-core.c | 4 ++-- drivers/hid/intel-ish-hid/ishtp/bus.c | 2 +- drivers/hsi/hsi_core.c | 2 +- drivers/hv/vmbus_drv.c | 4 ++-- drivers/input/serio/serio.c | 4 ++-- drivers/ipack/ipack.c | 4 ++-- drivers/macintosh/macio_asic.c | 2 +- drivers/mcb/mcb-core.c | 4 ++-- drivers/memstick/core/memstick.c | 6 +++--- drivers/misc/mei/bus.c | 4 ++-- drivers/misc/tifm_core.c | 4 ++-- drivers/mmc/core/bus.c | 4 ++-- drivers/mmc/core/sdio_bus.c | 4 ++-- drivers/net/phy/mdio_bus.c | 2 +- drivers/net/xen-netback/xenbus.c | 2 +- drivers/nvdimm/bus.c | 4 ++-- drivers/nvdimm/dax_devs.c | 2 +- drivers/nvdimm/dimm_devs.c | 2 +- drivers/nvdimm/nd-core.h | 10 +++++----- drivers/nvdimm/nd.h | 4 ++-- drivers/nvdimm/region_devs.c | 4 ++-- drivers/pci/pci-driver.c | 4 ++-- drivers/pcmcia/ds.c | 4 ++-- drivers/platform/x86/wmi.c | 4 ++-- drivers/rapidio/rio-driver.c | 4 ++-- drivers/rpmsg/rpmsg_core.c | 4 ++-- drivers/s390/cio/css.c | 4 ++-- drivers/s390/cio/device.c | 8 ++++---- drivers/s390/cio/scm.c | 2 +- drivers/s390/crypto/ap_bus.c | 4 ++-- drivers/scsi/scsi_sysfs.c | 4 ++-- drivers/slimbus/core.c | 4 ++-- drivers/soc/qcom/apr.c | 4 ++-- drivers/spi/spi.c | 2 +- drivers/spmi/spmi.c | 2 +- drivers/ssb/main.c | 4 ++-- drivers/staging/greybus/gbphy.c | 14 +++++++------- drivers/tee/tee_core.c | 2 +- drivers/usb/common/ulpi.c | 4 ++-- drivers/usb/core/driver.c | 6 +++--- drivers/usb/typec/bus.c | 4 ++-- drivers/virtio/virtio.c | 4 ++-- drivers/w1/w1.c | 10 +++++----- drivers/xen/pvcalls-back.c | 2 +- drivers/xen/xenbus/xenbus_probe_backend.c | 8 ++++---- drivers/xen/xenbus/xenbus_probe_frontend.c | 4 ++-- drivers/zorro/zorro-driver.c | 4 ++-- include/linux/device/bus.h | 2 +- include/linux/spi/spi.h | 2 +- include/linux/ssb/ssb.h | 2 +- include/sound/hdaudio.h | 2 +- include/xen/xenbus.h | 2 +- sound/aoa/soundbus/core.c | 6 +++--- sound/hda/hda_bus_type.c | 2 +- sound/hda/hdac_device.c | 2 +- 81 files changed, 160 insertions(+), 160 deletions(-) diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c index 8686e8c1c4e5ed..81c9f0a8880b0e 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/kernel/drivers.c b/arch/parisc/kernel/drivers.c index e7ee0c0c91d355..28f47285d448c0 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/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index 00ecac2c205b0d..770df9351aaa98 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/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c index 01122a208f9475..b78df3a15a72ed 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/drivers/acpi/bus.c b/drivers/acpi/bus.c index 0c05ccde1f7a6c..9531dd0fef5099 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/amba/bus.c b/drivers/amba/bus.c index ff7454a3805863..ce88af9eb562fb 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/auxiliary.c b/drivers/base/auxiliary.c index 8c5e659306177f..4d4c2c8d26c480 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/cpu.c b/drivers/base/cpu.c index 4c98849577d4ed..441eb5bdec7d89 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -336,7 +336,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) { diff --git a/drivers/base/platform.c b/drivers/base/platform.c index b10a130cd43341..262555b83beda3 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1353,9 +1353,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 */ diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 0a8469e0b13adf..7b39f010bbb371 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 774f307844b4e9..36cb091a33b464 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -124,9 +124,9 @@ static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv) /* * 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 1dc8a3557a4649..4819369faa8be1 100644 --- a/drivers/bus/mhi/ep/main.c +++ b/drivers/bus/mhi/ep/main.c @@ -1543,9 +1543,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 bf672de3513155..770fc81b7e9607 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 fca0d0669aa97e..554e1992edd44c 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 a180af11e03432..9aa99c369e48bc 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -172,7 +172,7 @@ static void sunxi_rsb_device_remove(struct device *dev) drv->remove(to_sunxi_rsb_device(dev)); } -static int sunxi_rsb_device_modalias(struct device *dev, struct kobj_uevent_env *env) +static int sunxi_rsb_device_modalias(const struct device *dev, struct kobj_uevent_env *env) { return of_device_uevent_modalias(dev, env); } diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index a38a0cc20d477b..b75dd77df7cef7 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -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 b631a052045619..3f02dc135a1200 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 1b1cf459ac779a..c9e1b48a1a5382 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 ab138004f64482..6749f2afb1b7c7 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 1dad813ee4a690..e3a384182fe77f 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 65bffde137e3f7..713582cc27d1f3 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/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c index 99d43948061260..f29d77ecf72db6 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/fpga/dfl.c b/drivers/fpga/dfl.c index b9aae85ba9308e..4d32c98c82fcf8 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -293,9 +293,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/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 497ef4b6a90a4d..36c24c2b0899f7 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 bdee16a0bb8e21..bc7271a00a94b6 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 e546c6431877fc..5714be7404707b 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 3e1803592bd4a2..a45e7034f0852b 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2664,9 +2664,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 f68aba8794fe50..81385ab37fa9a0 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 884066109699cf..8fda8f1d064d3b 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 3146710d4ac63c..f50aaa189df66f 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/input/serio/serio.c b/drivers/input/serio/serio.c index 15ce3202322f04..767fc9efb4a863 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 74d449858a61b2..cc1ecfd4992866 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/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 7f2b0107c73359..211ed9aa9edcd2 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -128,7 +128,7 @@ static int macio_device_resume(struct device * dev) return 0; } -static int macio_device_modalias(struct device *dev, struct kobj_uevent_env *env) +static int macio_device_modalias(const struct device *dev, struct kobj_uevent_env *env) { return of_device_uevent_modalias(dev, env); } diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c index b8ad4f16b4acdc..978fdfc19a06ae 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/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index 660df7d269fac2..bf766784545916 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 a81b890c7ee648..706ae85ca8f5c0 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 a3098fea3bf7e8..eee9b6581604ee 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 36679f4e9acce2..2c3074a605fc4a 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 babf21a0adeb62..5ec4e4ca52f08d 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/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 16e021b477f063..22b352c57ca2d5 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -1000,7 +1000,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 001636901ddae2..a78a25b872409a 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 b38d0355b0ac3b..92ce92fc99324b 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 7f4a9d28b67023..3bd61f2457885a 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 1fc081dcf63157..fb571666d33bdb 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 cc86ee09d7c081..ca2bbc57e75511 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 85ca5b4da3cf3b..cc166f99b0056b 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 83dbf398ea841a..8f134d63af1313 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/pci/pci-driver.c b/drivers/pci/pci-driver.c index a2ceeacc33eb6e..d934c27491c4c6 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 ace133b9f7d45d..c8087efa5e4aff 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/x86/wmi.c b/drivers/platform/x86/wmi.c index 46d1edc08f20a4..4fe7650dd01448 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -797,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 a72bb0a40fcfe4..e60e49769bed80 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 d6dde00efdae67..a2207c0cf43217 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 c7db953985002f..0723921902da61 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1402,9 +1402,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 9e0cf44ff9d4b2..b07ffd9ff11718 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 b6b4589c70bd71..6b21ba68c1fe62 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 b02c631f3b71ac..f4cc1720156f2a 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 981d1bab212071..a0dd711eb40827 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -534,9 +534,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/slimbus/core.c b/drivers/slimbus/core.c index 219483b79c09ce..d43873bb5fe6df 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/qcom/apr.c b/drivers/soc/qcom/apr.c index d51abb462ae5d3..30f81d6d9d9da5 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/spi/spi.c b/drivers/spi/spi.c index 15f174f4e0561a..b85e41a9dc34ef 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 55381592bb5a69..73551531ed437b 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 8a93c83cb6f805..ab080cf26c9fff 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/gbphy.c b/drivers/staging/greybus/gbphy.c index 5a5c17a4519b3f..6a7d8cf2a1ebc1 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 98da206cd7615b..452cbb8ad48416 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/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index d7c8461976ce09..67b780b256a9ec 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 7e7e119c253fb1..a0e076c6f3a495 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/typec/bus.c b/drivers/usb/typec/bus.c index 31c2a3130cadbb..dbcb96151558cc 100644 --- a/drivers/usb/typec/bus.c +++ b/drivers/usb/typec/bus.c @@ -321,9 +321,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/virtio/virtio.c b/drivers/virtio/virtio.c index b9a80aedee1b73..3893dc29eb2633 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 4a2ddf730a3acd..9d199fed962876 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 0d4f8f4f494888..8bf19bca5d3d53 100644 --- a/drivers/xen/pvcalls-back.c +++ b/drivers/xen/pvcalls-back.c @@ -1185,7 +1185,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 9c09f89d8278b3..da96c260e26b45 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 f44d5a64351e4a..3f3836cb72799b 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 96f068830549e0..025edfccedcf71 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/include/linux/device/bus.h b/include/linux/device/bus.h index 7b4a48b5159b62..87e4d029c91594 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -90,7 +90,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); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 9a32495fbb1fd0..2edf7f09239eec 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -223,7 +223,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 f9b53acb4e025d..1f326da289d3a6 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/sound/hdaudio.h b/include/sound/hdaudio.h index a6872537724d3d..1c45664e0e5acf 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 ef0505e72c2738..ac22cf08c09f74 100644 --- a/include/xen/xenbus.h +++ b/include/xen/xenbus.h @@ -117,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/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index c9579d97fbab19..39fb8fe4e6ab85 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 eea6b63f830558..4cd94178df9fa9 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 b7e5032b61c97c..accc9d279ce5aa 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); From 56d5f362ad0f8f60bc7c6fd5d7bc2b528d6963f5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Jan 2023 12:30:18 +0100 Subject: [PATCH 056/124] kobject: kset_uevent_ops: make uevent() callback take a const * The uevent() callback in struct kset_uevent_ops does not modify the kobject passed into it, so make the pointer const to enforce this restriction. When doing so, fix up all existing uevent() callbacks to have the correct signature to preserve the build. Cc: Christine Caulfield Cc: David Teigland Cc: Bob Peterson Cc: Andreas Gruenbacher Acked-by: Rafael J. Wysocki Acked-by: Hans de Goede Link: https://lore.kernel.org/r/20230111113018.459199-17-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 4 ++-- fs/dlm/lockspace.c | 4 ++-- fs/gfs2/sys.c | 6 +++--- include/linux/kobject.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index e39b6fa0eda6c8..e4b18f7ac58acb 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2387,9 +2387,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 */ diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index d0b4e2181a5f38..9b6cfc4c30e3d5 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 d87ea98cf53508..d8dfabb0bc1262 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -767,10 +767,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/include/linux/kobject.h b/include/linux/kobject.h index 58a5b75612e358..bdab370a24f4ef 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 { From b7810ea80ff0e1f7035c87296eb5ec77e4c13ec7 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 30 Jan 2023 15:28:18 +1100 Subject: [PATCH 057/124] driver core: fixup for "driver core: make struct bus_type.uevent() take a const *" After merging the driver-core tree, today's linux-next build (powerpc ppc64_defconfig) failed like this: arch/powerpc/platforms/ps3/system-bus.c:472:19: error: initialization of 'int (*)(const struct device *, struct kobj_uevent_env *)' from incompatible pointer type 'int (*)(struct device *, struct kobj_uevent_env *)' [-Werror=incompatible-pointer-types] 472 | .uevent = ps3_system_bus_uevent, | ^~~~~~~~~~~~~~~~~~~~~ arch/powerpc/platforms/ps3/system-bus.c:472:19: note: (near initialization for 'ps3_system_bus_type.uevent') arch/powerpc/platforms/pseries/ibmebus.c:436:22: error: initialization of 'int (*)(const struct device *, struct kobj_uevent_env *)' from incompatible pointer type 'int (*)(struct device *, struct kobj_uevent_env *)' [-Werror=incompatible-pointer-types] 436 | .uevent = ibmebus_bus_modalias, | ^~~~~~~~~~~~~~~~~~~~ arch/powerpc/platforms/pseries/ibmebus.c:436:22: note: (near initialization for 'ibmebus_bus_type.uevent') Signed-off-by: Stephen Rothwell Fixes: 2a81ada32f0e ("driver core: make struct bus_type.uevent() take a const *") Link: https://lore.kernel.org/r/20230130152818.03c00ea3@canb.auug.org.au Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/ps3.h | 2 +- arch/powerpc/platforms/ps3/system-bus.c | 2 +- arch/powerpc/platforms/pseries/ibmebus.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h index d503dbd7856cb8..a5f36546a05240 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/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 38a7e02295c8f2..d6b5f5ecd5152b 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 58b798a0e87984..bb9c1868278335 100644 --- a/arch/powerpc/platforms/pseries/ibmebus.c +++ b/arch/powerpc/platforms/pseries/ibmebus.c @@ -426,7 +426,7 @@ static struct attribute *ibmebus_bus_device_attrs[] = { }; ATTRIBUTE_GROUPS(ibmebus_bus_device); -static int ibmebus_bus_modalias(struct device *dev, struct kobj_uevent_env *env) +static int ibmebus_bus_modalias(const struct device *dev, struct kobj_uevent_env *env) { return of_device_uevent_modalias(dev, env); } From 90be1f15c39858a4f0f4346c39fa150697d231c1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 30 Jan 2023 18:10:59 +0100 Subject: [PATCH 058/124] driver core: soc: remove layering violation for the soc_bus The soc_bus code pokes around in the internal bus structures assuming that it "knows" if a field is not set that it has not been registered yet. That isn't a safe assumption, so just remove the layering violation entirely and keep track if the bus has been registered or not ourselves. Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230130171059.1784057-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/soc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/base/soc.c b/drivers/base/soc.c index 22130b5f789d9d..0fb1d4ab9d8a63 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)); From 2b8e35337605ca581f777cad73d7a6ac2ccbf6ec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 30 Jan 2023 13:17:46 +0200 Subject: [PATCH 059/124] container_of: Update header inclusions The commit 848dba781f19 ("container_of: remove container_of_safe()") removed the code that uses err.h. Replace the inclusion by stddef.h which provides offsetof() definition which is still in use. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20230130111746.59830-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- include/linux/container_of.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/container_of.h b/include/linux/container_of.h index 1d898f9158b45f..713890c867bea7 100644 --- a/include/linux/container_of.h +++ b/include/linux/container_of.h @@ -3,7 +3,7 @@ #define _LINUX_CONTAINER_OF_H #include -#include +#include #define typeof_member(T, m) typeof(((T*)0)->m) From ecaef469920fd6d2c7687f19081946f47684a423 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Tue, 24 Jan 2023 16:40:46 +0100 Subject: [PATCH 060/124] cacheinfo: Initialize variables in fetch_cache_info() Set potentially uninitialized variables to 0. This is particularly relevant when CONFIG_ACPI_PPTT is not set. Reported-by: kernel test robot Link: https://lore.kernel.org/all/202301052307.JYt1GWaJ-lkp@intel.com/ Reported-by: Dan Carpenter Link: https://lore.kernel.org/all/Y86iruJPuwNN7rZw@kili/ Fixes: 5944ce092b97 ("arch_topology: Build cacheinfo from primary CPU") Signed-off-by: Pierre Gondois Reviewed-by: Conor Dooley Link: https://lore.kernel.org/r/20230124154053.355376-2-pierre.gondois@arm.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/cacheinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 418a18acc8f9e0..f6573c335f4c4c 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -424,7 +424,7 @@ int allocate_cache_info(int cpu) int fetch_cache_info(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci; - unsigned int levels, split_levels; + unsigned int levels = 0, split_levels = 0; int ret; if (acpi_disabled) { From d931b83e62b1dd352fc326c0b1cf3be3ef19e113 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Tue, 24 Jan 2023 16:40:47 +0100 Subject: [PATCH 061/124] cacheinfo: Make default acpi_get_cache_info() return an error commit bd500361a937 ("ACPI: PPTT: Update acpi_find_last_cache_level() to acpi_get_cache_info()") updates the prototype of acpi_get_cache_info(). The cache 'levels' is update through a pointer and not the return value of the function. If CONFIG_ACPI_PPTT is not defined, acpi_get_cache_info() doesn't update its *levels and *split_levels parameters and returns 0. This can lead to a faulty behaviour. Make acpi_get_cache_info() return an error code if CONFIG_ACPI_PPTT is not defined. Also, In init_cache_level(), if no PPTT is present or CONFIG_ACPI_PPTT is not defined, instead of aborting if acpi_get_cache_info() returns an error code, just continue. This allows to try fetching the cache information from clidr_el1. Signed-off-by: Pierre Gondois Link: https://lore.kernel.org/r/20230124154053.355376-3-pierre.gondois@arm.com Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/cacheinfo.c | 2 +- include/linux/cacheinfo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c index 36c3b07cdf2d13..91677f4d3395de 100644 --- a/arch/arm64/kernel/cacheinfo.c +++ b/arch/arm64/kernel/cacheinfo.c @@ -64,7 +64,7 @@ int init_cache_level(unsigned int cpu) } else { ret = acpi_get_cache_info(cpu, &fw_level, NULL); if (ret < 0) - return ret; + fw_level = 0; } if (fw_level < 0) diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index dfef57077cd089..908e19d17f493d 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -100,7 +100,7 @@ static inline int acpi_get_cache_info(unsigned int cpu, unsigned int *levels, unsigned int *split_levels) { - return 0; + return -ENOENT; } #else int acpi_get_cache_info(unsigned int cpu, From 921e672dee91af86f8f9e44a067c735ebac0744b Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Tue, 24 Jan 2023 16:40:48 +0100 Subject: [PATCH 062/124] cacheinfo: Remove unused check in init_cache_level() commit e75d18cecbb3 ("arm64: cacheinfo: Fix incorrect assignment of signed error value to unsigned fw_level") checks the fw_level value in init_cache_level() in case the value is negative. Remove this check as the error code is not returned through fw_level anymore, and reset fw_level if acpi_get_cache_info() failed. This allows to try fetching the cache information from clidr_el1. Signed-off-by: Pierre Gondois Link: https://lore.kernel.org/r/20230124154053.355376-4-pierre.gondois@arm.com Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/cacheinfo.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c index 91677f4d3395de..3ba70985e3a270 100644 --- a/arch/arm64/kernel/cacheinfo.c +++ b/arch/arm64/kernel/cacheinfo.c @@ -67,9 +67,6 @@ int init_cache_level(unsigned int cpu) fw_level = 0; } - if (fw_level < 0) - return fw_level; - if (level < fw_level) { /* * some external caches not specified in CLIDR_EL1 From a69ea7a76d52353b17d7bedf43818c2578517e9e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 1 Feb 2023 13:56:42 +0100 Subject: [PATCH 063/124] maple: remove unneeded maple_bus_uevent() callback. The driver core recently changed the uevent bus callback to take a const pointer, and the maple_bus_uevent() was not correctly fixed up. Instead of fixing the function parameter types, just remove the callback entirely as it does not do anything, so it is not necessary. Cc: Yoshinori Sato Cc: Rich Felker Cc: Hans de Goede Cc: "Rafael J. Wysocki" Reported-by: Linux Kernel Functional Testing Reported-by: Naresh Kamboju Fixes: 2a81ada32f0e ("driver core: make struct bus_type.uevent() take a const *") Link: https://lore.kernel.org/r/20230201125642.624255-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/sh/maple/maple.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index e24e220e56eea1..e05473c5c267f4 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); From b4ce0bf7ab02c46676276ca1e8d4c5789528b439 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 31 Jan 2023 09:24:58 +0100 Subject: [PATCH 064/124] driver core: platform: removed unneeded variable from __platform_driver_probe() In the reworking of the function __platform_driver_probe() over the years, it turns out that the variable 'code' does not actually do anything or mean anything anymore and can be removed to simplify the logic when trying to read and understand what this function is actually doing. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230131082459.301603-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 262555b83beda3..423874269f9d51 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -906,7 +906,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,7 +932,7 @@ 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; @@ -944,11 +944,11 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv, */ spin_lock(&drv->driver.bus->p->klist_drivers.k_lock); drv->probe = platform_probe_fail; - if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) + if (list_empty(&drv->driver.p->klist_devices.k_list)) retval = -ENODEV; spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock); - if (code != retval) + if (retval) platform_driver_unregister(drv); return retval; } From 40b3880dc29b89c39139eba11eba2b3107dc2e38 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 31 Jan 2023 09:24:59 +0100 Subject: [PATCH 065/124] driver core: platform: simplify __platform_driver_probe() __platform_driver_probe() pokes around in some bus and driver private lists and locks in a way that is not needed at all. The code only wants to know if a device was bound to the driver that was registered, so walk all devices on the bus to see if there was a match. If there is not a match, return an error. This is the same logic as was originally present, but just done in a simpler and more obvious way that is not a layering violation. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230131082459.301603-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 423874269f9d51..77510e4f47de87 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -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 @@ -936,20 +943,17 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv, 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 (list_empty(&drv->driver.p->klist_devices.k_list)) - retval = -ENODEV; - spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock); - if (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); From 37e98d9bedb50644654fd196e38acad49903fadc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 1 Feb 2023 09:33:49 +0100 Subject: [PATCH 066/124] driver core: bus: move lock_class_key into dynamic structure Move the lock_class_key structure out of struct bus_type and into the dynamic structure we create already for all bus_types registered with the kernel. This saves on static space and removes one more writable field in struct bus_type. In the future, the same field can be moved out of the struct class logic because it shares this same private structure. Most everyone will never notice this change, as lockdep is not enabled in real systems so no memory or logic changes are happening for them. Cc: "Rafael J. Wysocki" Acked-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20230201083349.4038660-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 2 ++ drivers/base/bus.c | 5 ++++- include/linux/device/bus.h | 1 - 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 2208af509ce874..0e806f64107900 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -52,6 +52,8 @@ struct subsys_private { struct kset glue_dirs; struct class *class; + + struct lock_class_key lock_key; }; #define to_subsys_private(obj) container_of_const(obj, struct subsys_private, subsys.kobj) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index cf1b8f00b4c0c7..aa70b3a7d77873 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -154,6 +154,7 @@ 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; } @@ -743,7 +744,7 @@ int bus_register(struct bus_type *bus) { int retval; struct subsys_private *priv; - struct lock_class_key *key = &bus->lock_key; + struct lock_class_key *key; priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL); if (!priv) @@ -785,6 +786,8 @@ int bus_register(struct bus_type *bus) } 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); diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index 87e4d029c91594..e3094db1e9fa8d 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -112,7 +112,6 @@ struct bus_type { const struct iommu_ops *iommu_ops; struct subsys_private *p; - struct lock_class_key lock_key; bool need_parent_lock; }; From 5cdc03c5cf471a215c57e540cc86be613c0ba457 Mon Sep 17 00:00:00 2001 From: Longlong Xia Date: Thu, 2 Feb 2023 03:32:01 +0000 Subject: [PATCH 067/124] devtmpfs: convert to pr_fmt Use the pr_fmt() macro to prefix all the output with "devtmpfs: ". while at it, convert printk() to pr_(). Signed-off-by: Longlong Xia Link: https://lore.kernel.org/r/20230202033203.1239239-2-xialonglong1@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index e4bffeabf344ee..95ebc18ded5099 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 #include #include @@ -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; } From 8deb87b1e810dd558371e88ffd44339fbef27870 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 2 Feb 2023 15:16:20 +0100 Subject: [PATCH 068/124] drivers: base: component: fix memory leak with using debugfs_lookup() When calling debugfs_lookup() the result must have dput() called on it, otherwise the memory will leak over time. To make things simpler, just call debugfs_lookup_and_remove() instead which handles all of the logic at once. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230202141621.2296458-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/component.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/component.c b/drivers/base/component.c index 5eadeac6c53221..7dbf14a1d91577 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 From 36c893d3a759ae7c91ee7d4871ebfc7504f08c40 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 2 Feb 2023 15:16:21 +0100 Subject: [PATCH 069/124] drivers: base: dd: fix memory leak with using debugfs_lookup() When calling debugfs_lookup() the result must have dput() called on it, otherwise the memory will leak over time. To make things simpler, just call debugfs_lookup_and_remove() instead which handles all of the logic at once. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230202141621.2296458-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 817ef27a78f7eb..8def2ba08a8211 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -370,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); From 8518e9db9f95d7beb453e46ee97e1a630680c4b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 4 Feb 2023 05:41:26 +0000 Subject: [PATCH 070/124] const_structs.checkpatch.pl: add kobj_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit ee6d3dd4ed48 ("driver core: make kobj_type constant.") the driver core allows the usage of const struct kobj_type. Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20230204-kobj_type-checkpatch-v1-1-9a94b04adbb2@weissschuh.net Signed-off-by: Greg Kroah-Hartman --- scripts/const_structs.checkpatch | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch index 1eeb7b42c5b9fa..dc39d938ea77d0 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 From dda6b81f17ad8e72f8bc151c876cd335a471e268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 4 Feb 2023 21:59:50 +0000 Subject: [PATCH 071/124] kobject: make dynamic_kobj_ktype and kset_ktype const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit ee6d3dd4ed48 ("driver core: make kobj_type constant.") the driver core allows the usage of const struct kobj_type. Take advantage of this to constify the structure definitions to prevent modification at runtime. Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20230204-kobj_type-kobj-v1-1-ddd1b4ef8ab5@weissschuh.net Signed-off-by: Greg Kroah-Hartman --- lib/kobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/kobject.c b/lib/kobject.c index d20ce15eec2d05..6e2f0bee356042 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -737,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, }; @@ -921,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, From c83d9ab42f1ef70d81bb3c637a12c098a9a05057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 4 Feb 2023 22:36:58 +0000 Subject: [PATCH 072/124] driver core: make kobj_type structures constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit ee6d3dd4ed48 ("driver core: make kobj_type constant.") the driver core allows the usage of const struct kobj_type. Take advantage of this to constify the structure definitions to prevent modification at runtime. Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20230204-kobj_type-driver-core-v1-1-b9f809419f2c@weissschuh.net Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 4 ++-- drivers/base/class.c | 2 +- drivers/base/core.c | 4 ++-- drivers/base/swnode.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index aa70b3a7d77873..d6b4a5d5a43c41 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -91,7 +91,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, }; @@ -159,7 +159,7 @@ static void bus_release(struct kobject *kobj) bus->p = NULL; } -static struct kobj_type bus_ktype = { +static const struct kobj_type bus_ktype = { .sysfs_ops = &bus_sysfs_ops, .release = bus_release, }; diff --git a/drivers/base/class.c b/drivers/base/class.c index a38b0d7d681d70..89d4528fcc1a98 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -77,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, diff --git a/drivers/base/core.c b/drivers/base/core.c index e4b18f7ac58acb..3c4acf4b34d35b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2354,7 +2354,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, @@ -2992,7 +2992,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 diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index da3c1c2cb9a808..1886995a0b3a30 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, }; From 862f6a84d1bf01435fdd6aa8b2811c88ab1f06f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 8 Feb 2023 03:54:51 +0000 Subject: [PATCH 073/124] samples/kobject: make kobj_type structure constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit ee6d3dd4ed48 ("driver core: make kobj_type constant.") the driver core allows the usage of const struct kobj_type. Take advantage of this to constify the structure definition to prevent modification at runtime. Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20230208-kobj_type-samples-v1-1-fca804a8e9f3@weissschuh.net Signed-off-by: Greg Kroah-Hartman --- samples/kobject/kset-example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c index 52f1acabd47911..34245228271937 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, From 5f5139974c2030e0937d3ae01f17da1238281f11 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 2 Feb 2023 16:12:14 +0100 Subject: [PATCH 074/124] kernel/time/test_udelay.c: fix memory leak with using debugfs_lookup() When calling debugfs_lookup() the result must have dput() called on it, otherwise the memory will leak over time. To make things simpler, just call debugfs_lookup_and_remove() instead which handles all of the logic at once. Link: https://lore.kernel.org/r/20230202151214.2306822-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- kernel/time/test_udelay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/test_udelay.c b/kernel/time/test_udelay.c index 13b11eb62685e4..20d5df631570ec 100644 --- a/kernel/time/test_udelay.c +++ b/kernel/time/test_udelay.c @@ -149,7 +149,7 @@ module_init(udelay_test_init); static void __exit udelay_test_exit(void) { mutex_lock(&udelay_test_lock); - debugfs_remove(debugfs_lookup(DEBUGFS_FILENAME, NULL)); + debugfs_lookup_and_remove(DEBUGFS_FILENAME, NULL); mutex_unlock(&udelay_test_lock); } From a0bc3f78d0fffa8be1a73bf945a43bfe1c2871c1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 2 Feb 2023 16:15:15 +0100 Subject: [PATCH 075/124] kernel/power/energy_model.c: fix memory leak with using debugfs_lookup() When calling debugfs_lookup() the result must have dput() called on it, otherwise the memory will leak over time. To make things simpler, just call debugfs_lookup_and_remove() instead which handles all of the logic at once. Cc: "Rafael J. Wysocki" Cc: Pavel Machek Cc: Len Brown Link: https://lore.kernel.org/r/20230202151515.2309543-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- kernel/power/energy_model.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c index f82111837b8d1d..7b44f5b89fa154 100644 --- a/kernel/power/energy_model.c +++ b/kernel/power/energy_model.c @@ -87,10 +87,7 @@ static void em_debug_create_pd(struct device *dev) static void em_debug_remove_pd(struct device *dev) { - struct dentry *debug_dir; - - debug_dir = debugfs_lookup(dev_name(dev), rootdir); - debugfs_remove_recursive(debug_dir); + debugfs_lookup_and_remove(dev_name(dev), rootdir); } static int __init em_debug_init(void) From 2bb3669f576559db273efe49e0e69f82450efbca Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 2 Feb 2023 16:16:33 +0100 Subject: [PATCH 076/124] kernel/fail_function: fix memory leak with using debugfs_lookup() When calling debugfs_lookup() the result must have dput() called on it, otherwise the memory will leak over time. To make things simpler, just call debugfs_lookup_and_remove() instead which handles all of the logic at once. Cc: Andrew Morton Reviewed-by: Yang Yingliang Link: https://lore.kernel.org/r/20230202151633.2310897-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- kernel/fail_function.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel/fail_function.c b/kernel/fail_function.c index a7ccd2930c5f46..d971a018931976 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) From 3a2dbc510c437ca392516b0105bad8e7970e6614 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:41:53 -0800 Subject: [PATCH 077/124] driver core: fw_devlink: Don't purge child fwnode's consumer links When a device X is bound successfully to a driver, if it has a child firmware node Y that doesn't have a struct device created by then, we delete fwnode links where the child firmware node Y is the supplier. We did this to avoid blocking the consumers of the child firmware node Y from deferring probe indefinitely. While that a step in the right direction, it's better to make the consumers of the child firmware node Y to be consumers of the device X because device X is probably implementing whatever functionality is represented by child firmware node Y. By doing this, we capture the device dependencies more accurately and ensure better probe/suspend/resume ordering. Signed-off-by: Saravana Kannan Tested-by: Colin Foster Tested-by: Sudeep Holla Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-2-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 97 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 18 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 3c4acf4b34d35b..040c8072fd3ede 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,22 +75,18 @@ 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) { 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; + 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); @@ -100,9 +97,17 @@ int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup) 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); + mutex_unlock(&fwnode_link_lock); return ret; } @@ -181,6 +186,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); + __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); +} + #ifdef CONFIG_SRCU static DEFINE_MUTEX(device_links_lock); DEFINE_STATIC_SRCU(device_links_srcu); @@ -1267,16 +1317,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); @@ -1855,7 +1912,11 @@ 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); + 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 From 411c0d58ca6faa9bc4b9f5382118a31c7bb92a6f Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:41:54 -0800 Subject: [PATCH 078/124] driver core: fw_devlink: Improve check for fwnode with no device/driver fw_devlink shouldn't defer the probe of a device to wait on a supplier that'll never have a struct device or will never be probed by a driver. We currently check if a supplier falls into this category, but don't check its ancestors. We need to check the ancestors too because if the ancestor will never probe, then the supplier will never probe either. Signed-off-by: Saravana Kannan Tested-by: Colin Foster Tested-by: Sudeep Holla Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-3-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 040c8072fd3ede..3daaa7ffe75173 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1867,6 +1867,35 @@ static int fw_devlink_relax_cycle(struct device *con, void *sup) return ret; } +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_create_devlink - Create a device link from a consumer to fwnode * @con: consumer device for the device link @@ -1948,9 +1977,16 @@ static int fw_devlink_create_devlink(struct device *con, goto out; } - /* Supplier that's already initialized without a struct device. */ - if (sup_handle->flags & FWNODE_FLAG_INITIALIZED) + /* + * Supplier or supplier's ancestor already initialized without a struct + * device or being probed by a driver. + */ + if (fwnode_init_without_drv(sup_handle) || + fwnode_ancestor_init_without_drv(sup_handle)) { + dev_dbg(con, "Not linking %pfwP - Might never probe\n", + sup_handle); return -EINVAL; + } /* * DL_FLAG_SYNC_STATE_ONLY doesn't block probing and supports From 8640166f01fe42f2e4a73ab92c797b97b467927d Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:41:55 -0800 Subject: [PATCH 079/124] soc: renesas: Move away from using OF_POPULATED for fw_devlink The OF_POPULATED flag was set to let fw_devlink know that the device tree node will not have a struct device created for it. This information is used by fw_devlink to avoid deferring the probe of consumers of this device tree node. Let's use fwnode_dev_initialized() instead because it achieves the same effect without using OF specific flags. This allows more generic code to be written in driver core. Signed-off-by: Saravana Kannan Reviewed-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-4-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/soc/renesas/rcar-sysc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index b0a80de34c9885..eed47696e82526 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); From 38dfa56b3db354b4bd399fc686c3e74ad32ffa57 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:41:56 -0800 Subject: [PATCH 080/124] gpiolib: Clear the gpio_device's fwnode initialized flag before adding Registering an irqdomain sets the flag for the fwnode. But having the flag set when a device is added is interpreted by fw_devlink to mean the device has already been initialized and will never probe. This prevents fw_devlink from creating device links with the gpio_device as a supplier. So, clear the flag before adding the device. Signed-off-by: Saravana Kannan Acked-by: Bartosz Golaszewski Tested-by: Colin Foster Tested-by: Sudeep Holla Reviewed-by: Andy Shevchenko Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-5-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpiolib.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 939c776b948813..bdb9493857ebbc 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -578,6 +578,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; From 67cad5c67019c38126b749621665b6723d3ae7e6 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:41:57 -0800 Subject: [PATCH 081/124] driver core: fw_devlink: Add DL_FLAG_CYCLE support to device links fw_devlink uses DL_FLAG_SYNC_STATE_ONLY device link flag for two purposes: 1. To allow a parent device to proxy its child device's dependency on a supplier so that the supplier doesn't get its sync_state() callback before the child device/consumer can be added and probed. In this usage scenario, we need to ignore cycles for ensure correctness of sync_state() callbacks. 2. When there are dependency cycles in firmware, we don't know which of those dependencies are valid. So, we have to ignore them all wrt probe ordering while still making sure the sync_state() callbacks come correctly. However, when detecting dependency cycles, there can be multiple dependency cycles between two devices that we need to detect. For example: A -> B -> A and A -> C -> B -> A. To detect multiple cycles correct, we need to be able to differentiate DL_FLAG_SYNC_STATE_ONLY device links used for (1) vs (2) above. To allow this differentiation, add a DL_FLAG_CYCLE that can be use to mark use case (2). We can then use the DL_FLAG_CYCLE to decide which DL_FLAG_SYNC_STATE_ONLY device links to follow when looking for dependency cycles. Fixes: 2de9d8e0d2fe ("driver core: fw_devlink: Improve handling of cyclic dependencies") Signed-off-by: Saravana Kannan Tested-by: Colin Foster Tested-by: Sudeep Holla Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-6-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 28 ++++++++++++++++++---------- include/linux/device.h | 1 + 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 3daaa7ffe75173..ac19752422e0ed 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -322,6 +322,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. @@ -348,8 +354,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) @@ -422,8 +427,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); } @@ -684,7 +688,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) @@ -753,8 +758,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))) @@ -770,6 +773,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(); @@ -1729,7 +1736,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); @@ -1853,8 +1860,8 @@ static int fw_devlink_relax_cycle(struct device *con, void *sup) return ret; list_for_each_entry(link, &con->links.consumers, s_node) { - if ((link->flags & ~DL_FLAG_INFERRED) == - (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) + if (!(link->flags & DL_FLAG_CYCLE) && + device_link_flag_is_sync_state_only(link->flags)) continue; if (!fw_devlink_relax_cycle(link->consumer, sup)) @@ -1863,6 +1870,7 @@ static int fw_devlink_relax_cycle(struct device *con, void *sup) ret = 1; fw_devlink_relax_link(link); + link->flags |= DL_FLAG_CYCLE; } return ret; } diff --git a/include/linux/device.h b/include/linux/device.h index 90aaf308c2594b..1508e637bb2666 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -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. From 6a6dfdf8b3ff337be5a447e9f4e71969f18370ad Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:41:58 -0800 Subject: [PATCH 082/124] driver core: fw_devlink: Allow marking a fwnode link as being part of a cycle To improve detection and handling of dependency cycles, we need to be able to mark fwnode links as being part of cycles. fwnode links marked as being part of a cycle should not block their consumers from probing. Fixes: 2de9d8e0d2fe ("driver core: fw_devlink: Improve handling of cyclic dependencies") Signed-off-by: Saravana Kannan Tested-by: Colin Foster Tested-by: Sudeep Holla Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-7-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 50 +++++++++++++++++++++++++++++++++--------- include/linux/fwnode.h | 11 +++++++++- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index ac19752422e0ed..6639f90cf30133 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -76,13 +76,15 @@ static bool fw_devlink_best_effort; * are ignored and there is no reference counting. */ static int __fwnode_link_add(struct fwnode_handle *con, - struct fwnode_handle *sup) + struct fwnode_handle *sup, u8 flags) { struct fwnode_link *link; list_for_each_entry(link, &sup->consumers, s_hook) - if (link->consumer == con) + if (link->consumer == con) { + link->flags |= flags; return 0; + } link = kzalloc(sizeof(*link), GFP_KERNEL); if (!link) @@ -92,6 +94,7 @@ static int __fwnode_link_add(struct fwnode_handle *con, 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); @@ -106,7 +109,7 @@ 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); + ret = __fwnode_link_add(con, sup, 0); mutex_unlock(&fwnode_link_lock); return ret; } @@ -126,6 +129,19 @@ static void __fwnode_link_del(struct fwnode_link *link) kfree(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 @@ -199,7 +215,7 @@ static void __fwnode_links_move_consumers(struct fwnode_handle *from, struct fwnode_link *link, *tmp; list_for_each_entry_safe(link, tmp, &from->consumers, s_hook) { - __fwnode_link_add(link->consumer, to); + __fwnode_link_add(link->consumer, to, link->flags); __fwnode_link_del(link); } } @@ -1041,6 +1057,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. @@ -1068,11 +1099,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, @@ -1261,7 +1289,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); } diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 89b9bdfca925c5..fdf2ee0285b7af 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; }; /** From cd115c0409f283edde94bd5a9a42dc42bee0aba8 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:41:59 -0800 Subject: [PATCH 083/124] driver core: fw_devlink: Consolidate device link flag computation Consolidate the code that computes the flags to be used when creating a device link from a fwnode link. Fixes: 2de9d8e0d2fe ("driver core: fw_devlink: Improve handling of cyclic dependencies") Signed-off-by: Saravana Kannan Tested-by: Colin Foster Tested-by: Sudeep Holla Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-8-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 28 +++++++++++++++------------- include/linux/fwnode.h | 1 - 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 6639f90cf30133..0a8a5ab344c156 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1727,8 +1727,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; } @@ -1938,7 +1941,7 @@ static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode) * 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. @@ -1955,10 +1958,17 @@ static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode) * 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 @@ -2091,7 +2101,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; @@ -2121,14 +2130,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; @@ -2169,19 +2177,13 @@ 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; diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index fdf2ee0285b7af..5700451b300fb5 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -207,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); From 3fb16866b51ded6c016b664caad53f8d4fd9dc56 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:42:00 -0800 Subject: [PATCH 084/124] driver core: fw_devlink: Make cycle detection more robust fw_devlink could only detect a single and simple cycle because it relied mainly on device link cycle detection code that only checked for cycles between devices. The expectation was that the firmware wouldn't have complicated cycles and multiple cycles between devices. That expectation has been proven to be wrong. For example, fw_devlink could handle: +-+ +-+ |A+------> |B+ +-+ +++ ^ | | | +----------+ But it couldn't handle even something as "simple" as: +---------------------+ | | v | +-+ +-+ +++ |A+------> |B+------> |C| +-+ +++ +-+ ^ | | | +----------+ But firmware has even more complicated cycles like: +---------------------+ | | v | +-+ +---+ +++ +--+A+------>| B +-----> |C|<--+ | +-+ ++--+ +++ | | ^ | ^ | | | | | | | | | +---------+ +---------+ | | | +------------------------------+ And this is without including parent child dependencies or nodes in the cycle that are just firmware nodes that'll never have a struct device created for them. The proper way to treat these devices it to not force any probe ordering between them, while still enforce dependencies between node in the cycles (A, B and C) and their consumers. So this patch goes all out and just deals with all types of cycles. It does this by: 1. Following dependencies across device links, parent-child and fwnode links. 2. When it find cycles, it mark the device links and fwnode links as such instead of just deleting them or making the indistinguishable from proxy SYNC_STATE_ONLY device links. This way, when new nodes get added, we can immediately find and mark any new cycles whether the new node is a device or firmware node. Fixes: 2de9d8e0d2fe ("driver core: fw_devlink: Improve handling of cyclic dependencies") Signed-off-by: Saravana Kannan Tested-by: Colin Foster Tested-by: Sudeep Holla Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-9-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 248 +++++++++++++++++++++++--------------------- 1 file changed, 129 insertions(+), 119 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 0a8a5ab344c156..2712a1a1e9590c 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1866,47 +1866,6 @@ static void fw_devlink_unblock_consumers(struct device *dev) device_links_write_unlock(); } -/** - * 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. - */ -static int fw_devlink_relax_cycle(struct device *con, void *sup) -{ - struct device_link *link; - int ret; - - if (con == sup) - return 1; - - ret = device_for_each_child(con, sup, fw_devlink_relax_cycle); - if (ret) - return ret; - - list_for_each_entry(link, &con->links.consumers, s_node) { - if (!(link->flags & DL_FLAG_CYCLE) && - device_link_flag_is_sync_state_only(link->flags)) - continue; - - if (!fw_devlink_relax_cycle(link->consumer, sup)) - continue; - - ret = 1; - - fw_devlink_relax_link(link); - link->flags |= DL_FLAG_CYCLE; - } - return ret; -} static bool fwnode_init_without_drv(struct fwnode_handle *fwnode) { @@ -1937,6 +1896,111 @@ static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode) return false; } +/** + * __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 bool __fw_devlink_relax_cycles(struct device *con, + struct fwnode_handle *sup_handle) +{ + struct device *sup_dev = NULL, *par_dev = NULL; + struct fwnode_link *link; + struct device_link *dev_link; + bool ret = false; + + if (!sup_handle) + return false; + + /* + * 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; + + sup_handle->flags |= FWNODE_FLAG_VISITED; + + sup_dev = get_dev_from_fwnode(sup_handle); + + /* Termination condition. */ + if (sup_dev == con) { + ret = true; + goto out; + } + + /* + * 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; +} + /** * fw_devlink_create_devlink - Create a device link from a consumer to fwnode * @con: consumer device for the device link @@ -1989,6 +2053,21 @@ static int fw_devlink_create_devlink(struct device *con, fwnode_is_ancestor_of(sup_handle, con->fwnode)) return -EINVAL; + /* + * 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 @@ -2002,23 +2081,16 @@ 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; } @@ -2031,49 +2103,12 @@ static int fw_devlink_create_devlink(struct device *con, */ if (fwnode_init_without_drv(sup_handle) || fwnode_ancestor_init_without_drv(sup_handle)) { - dev_dbg(con, "Not linking %pfwP - Might never probe\n", + dev_dbg(con, "Not linking %pfwf - might never become dev\n", sup_handle); 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. - */ - 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; - } - + ret = -EAGAIN; out: put_device(sup_dev); return ret; @@ -2156,10 +2191,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 @@ -2180,7 +2212,6 @@ static void __fw_devlink_link_to_suppliers(struct device *dev, 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, link); @@ -2188,27 +2219,6 @@ static void __fw_devlink_link_to_suppliers(struct device *dev, 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); } /* From 4a032827daa89350365166b19d14d82fe8219128 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:42:01 -0800 Subject: [PATCH 085/124] of: property: Simplify of_link_to_phandle() The driver core now: - Has the parent device of a supplier pick up the consumers if the supplier never has a device created for it. - Ignores a supplier if the supplier has no parent device and will never be probed by a driver And already prevents creating a device link with the consumer as a supplier of a parent. So, we no longer need to find the "compatible" node of the supplier or do any other checks in of_link_to_phandle(). We simply need to make sure that the supplier is available in DT. Signed-off-by: Saravana Kannan Tested-by: Colin Foster Tested-by: Sudeep Holla Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-10-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/of/property.c | 84 +++++++------------------------------------ 1 file changed, 13 insertions(+), 71 deletions(-) diff --git a/drivers/of/property.c b/drivers/of/property.c index 134cfc980b70b3..c651aad6f34b1d 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; } /** From e2bbea770cafb7e19bbb6cd77fad3c1c6fb4cca5 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:42:02 -0800 Subject: [PATCH 086/124] irqchip/irq-imx-gpcv2: Mark fwnode device as not initialized Since this device is only partially initialized by the irqchip driver, we need to mark the fwnode device as not initialized. This is to let fw_devlink know that the device will be completely initialized at a later point. That way, fw_devlink will continue to defer the probe of the power domain consumers till the power domain driver successfully binds to the struct device and completes the initialization of the device. Signed-off-by: Saravana Kannan Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-11-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/irqchip/irq-imx-gpcv2.c | 1 + drivers/soc/imx/gpcv2.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c index b9c22f764b4d9e..8a0e82067924eb 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/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 7a47d14fde445d..4b3300b090a8aa 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) { From 96da4a99ce507bb98e2ba77018a2f91999c8c12b Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:42:03 -0800 Subject: [PATCH 087/124] firmware: arm_scmi: Set fwnode for the scmi_device This allows fw_devlink to track and enforce supplier-consumer dependencies for scmi_device. Signed-off-by: Saravana Kannan Acked-by: Sudeep Holla Tested-by: Colin Foster Tested-by: Sudeep Holla Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-12-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/arm_scmi/bus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index 35bb70724d44bc..cc2eba06757570 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -12,6 +12,7 @@ #include #include #include +#include #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); From fb42378dcc7f247df56f0ecddfdae85487495fbc Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Mon, 6 Feb 2023 17:42:04 -0800 Subject: [PATCH 088/124] mtd: mtdpart: Don't create platform device that'll never probe These "nvmem-cells" platform devices never get probed because there's no platform driver for it and it's never used anywhere else. So it's a waste of memory. These devices also cause fw_devlink to block nvmem consumers of "nvmem-cells" partition from probing because the supplier device never probes. So stop creating platform devices for nvmem-cells partitions to avoid wasting memory and to avoid blocking probing of consumers. Reported-by: Maxim Kiselev Fixes: bcdf0315a61a ("mtd: call of_platform_populate() for MTD partitions") Signed-off-by: Saravana Kannan Tested-by: Maksim Kiselev Tested-by: Douglas Anderson Tested-by: Geert Uytterhoeven Tested-by: Luca Weiss # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/20230207014207.1678715-13-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/mtdpart.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index d442fa94c87200..85f5ee6f06fc63 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) From 789be03a600842ef461968cc5a2d458f51f319b2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:10 +0100 Subject: [PATCH 089/124] driver core: add local subsys_get and subsys_put functions We need to control the reference count of the subsys private structure instead of directly manipulating the kset reference count of it, so wrap that logic up in a subsys_get() and subsys_put() function to make it more obvious as to what is happening. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/base/base.h b/drivers/base/base.h index 0e806f64107900..9e06c18c7a6442 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -57,6 +57,19 @@ struct subsys_private { }; #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; struct klist klist_devices; From 273afac615adccf97bd4e70ebfb27074f1ff22b9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:11 +0100 Subject: [PATCH 090/124] driver core: bus: implement bus_get/put() without the private pointer In the quest to make 'struct bus_type' constant and in read-only memory, we need to stop using the private pointer to the subsys_private structure. First step in doing this is to create a helper function that turns a 'struct bus_type' into 'struct subsys_private' called bus_to_subsys(). bus_to_subsys() walks the list of registered busses in the system and finds the matching one based on the pointer to the bus_type itself. As this is a short list, and this function is not on any fast path, it should not be noticable. Implement bus_get() and bus_put() using this new helper function. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-3-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 61 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d6b4a5d5a43c41..8f46ab84e81a05 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -24,6 +24,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 +42,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, @@ -177,8 +224,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) From e0766ea4c8f8f94a605e291aa3672a703dc1d2e4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:12 +0100 Subject: [PATCH 091/124] driver core: bus: constantify the bus_find_* functions All of the bus find and iterator functions do not modify the struct bus_type passed to them, so mark them as constant to enforce this rule. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-4-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 6 +++--- include/linux/device/bus.h | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 8f46ab84e81a05..b27ddf957f8b9c 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -331,7 +331,7 @@ 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 klist_iter i; @@ -365,7 +365,7 @@ 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)) { @@ -416,7 +416,7 @@ 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 klist_iter i; diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index e3094db1e9fa8d..f0c8bf91b07af2 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -149,9 +149,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 */ -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)); /** @@ -161,7 +161,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) { @@ -175,7 +175,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); } @@ -187,7 +187,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); } @@ -198,7 +198,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); @@ -211,7 +211,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); } @@ -226,19 +226,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 -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, From 0396f2863f7af3c588033d270f7d979d11cd4708 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:13 +0100 Subject: [PATCH 092/124] driver core: bus: convert bus_create/remove_file to be constant bus_create_file() and bus_remove_file() can be made to take a constant bus pointer, as it should not be modifying anything in the bus structure. Make this change and move the functions to use the internal subsys_get/put() logic as well, to prevent the use of the back-pointer in struct bus_type. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-5-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 28 +++++++++++++++++----------- include/linux/device/bus.h | 5 ++--- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index b27ddf957f8b9c..6552d385fcb90b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -175,24 +175,30 @@ 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); diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index f0c8bf91b07af2..f6537f5fc53538 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -135,9 +135,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); From a00fdb988d81200e4d81b81e525b8f90e7d51591 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:14 +0100 Subject: [PATCH 093/124] driver core: bus: sysfs function cleanups Convert the drivers_autoprobe show/store and uevent sysfs callbacks to use bus_to_subsys() and not use the back-pointer to the private structure. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-6-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 6552d385fcb90b..d30a07ff8ab2a0 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -277,16 +277,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; } @@ -769,10 +784,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() From 5221b82d46f26903cf3161fb7d1fc006170811e0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:15 +0100 Subject: [PATCH 094/124] driver core: bus: bus_add/probe/remove_device() cleanups Convert the bus_add_device(), bus_probe_device(), and bus_remove_device() functions to use bus_to_subsys() and not use the back-pointer to the private structure. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-7-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 87 ++++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 33 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d30a07ff8ab2a0..a32975028aee9b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -466,32 +466,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; } @@ -503,20 +517,21 @@ int bus_add_device(struct device *dev) */ 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); } /** @@ -531,21 +546,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); @@ -553,7 +567,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) From 3465e2e4a24eef9bc9f21aa29d83fd7000c1da48 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:16 +0100 Subject: [PATCH 095/124] driver core: bus: bus_register/unregister() cleanups Convert the bus_register() and bus_unregister() functions to use bus_to_subsys() and not use the back-pointer to the private structure. Because bus_add_groups() and bus_remove_groups() were only called in one place, remove those one-line-wrapper functions and call the real sysfs group function where it is needed instead, saving another layer of indirection. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-8-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 54 ++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index a32975028aee9b..d515a83635223d 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -774,18 +774,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); @@ -839,6 +827,7 @@ int bus_register(struct bus_type *bus) { int retval; struct subsys_private *priv; + struct kobject *bus_kobj; struct lock_class_key *key; priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL); @@ -850,12 +839,13 @@ int bus_register(struct bus_type *bus) 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); @@ -866,15 +856,13 @@ 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; @@ -891,7 +879,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; @@ -901,15 +889,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); + kfree(priv); bus->p = NULL; return retval; } @@ -924,15 +912,25 @@ EXPORT_SYMBOL_GPL(bus_register); */ void bus_unregister(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); From adac0375380a7d3e50194cc5b03b676b0321bded Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:17 +0100 Subject: [PATCH 096/124] driver core: bus: subsys_interface_register/unregister() cleanups Convert the subsys_interface_register and subsys_interface_unregister() functions to use bus_to_subsys() and not use the back-pointer to the private structure. This also requires changing the parameters on subsys_dev_iter_init() to iterate over the list properly. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-9-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d515a83635223d..b831173071ec8b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -1023,7 +1023,7 @@ struct subsys_dev_iter { /** * 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 * @@ -1032,14 +1032,14 @@ struct subsys_dev_iter { * otherwise if it is NULL, the iteration starts at the beginning of * the list. */ -static void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys, +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; } @@ -1084,26 +1084,31 @@ static void subsys_dev_iter_exit(struct subsys_dev_iter *iter) 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; } @@ -1111,26 +1116,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); + mutex_unlock(&sp->mutex); - bus_put(subsys); + /* + * 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); From beea7892d4339e50f15e5131d51a95503678fdf6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:18 +0100 Subject: [PATCH 097/124] driver core: bus: bus_get_kset() cleanup Convert the bus_get_kset() function function to use bus_to_subsys() and not use the back-pointer to the private structure. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-10-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index b831173071ec8b..105b6af924af35 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -956,7 +956,16 @@ void bus_notify(struct device *dev, enum bus_notifier_event value) struct kset *bus_get_kset(struct bus_type *bus) { - return &bus->p->subsys; + 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_kset); From 32a8121a19c4936672440c96371f6a8c2b0c3d4d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:19 +0100 Subject: [PATCH 098/124] driver core: bus: bus_register/unregister_notifier() cleanups Convert the bus_register_notifier() and bus_unregister_notifier() public functions to use bus_to_subsys() and not use the back-pointer to the private structure as well as the bus_notify() function. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-11-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 105b6af924af35..81c0f7ff29a2fd 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -936,22 +936,40 @@ EXPORT_SYMBOL_GPL(bus_unregister); int bus_register_notifier(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) { - 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); void bus_notify(struct device *dev, enum bus_notifier_event value) { - struct bus_type *bus = dev->bus; + struct subsys_private *sp = bus_to_subsys(dev->bus); - if (bus) - blocking_notifier_call_chain(&bus->p->bus_notifier, value, dev); + if (!sp) + return; + + blocking_notifier_call_chain(&sp->bus_notifier, value, dev); + subsys_put(sp); } struct kset *bus_get_kset(struct bus_type *bus) From e4f056825ff5939254701d02ff3833ff27116225 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:20 +0100 Subject: [PATCH 099/124] driver core: bus: bus_add/remove_driver() cleanups Convert the bus_add_driver() and bus_remove_driver() functions to use bus_to_subsys() and not use the back-pointer to the private structure. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-12-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 81c0f7ff29a2fd..eb8fb42afd4b70 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -636,15 +636,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) { @@ -654,14 +657,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; @@ -673,7 +676,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", @@ -698,7 +701,7 @@ int bus_add_driver(struct device_driver *drv) /* drv->p is freed in driver_release() */ drv->p = NULL; out_put_bus: - bus_put(bus); + subsys_put(sp); return error; } @@ -712,19 +715,29 @@ int bus_add_driver(struct device_driver *drv) */ 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 */ From 83b9148df2c95e23d0fcf1f714dec88ce5a0468b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:21 +0100 Subject: [PATCH 100/124] driver core: bus: bus iterator cleanups Convert the bus_for_each_dev(), bus_find_device, and bus_for_each_drv() functions to use bus_to_subsys() and not use the back-pointer to the private structure. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-13-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index eb8fb42afd4b70..c6d310fd0ecfcf 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -355,18 +355,20 @@ static struct device *next_device(struct klist_iter *i) 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); @@ -390,18 +392,20 @@ 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); @@ -440,18 +444,20 @@ static struct device_driver *next_driver(struct klist_iter *i) 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); From b5aaecb82ac0d008ddec8132979398b9b4e925fc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:22 +0100 Subject: [PATCH 101/124] driver core: bus: clean up bus_sort_breadthfirst() Convert the bus_sort_breadthfirst() function to use bus_to_subsys() and not use the back-pointer to the private structure. This also allows us to get rid of bus_get_device_klist() which was only being used by this one internal function. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-14-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c6d310fd0ecfcf..87c44661dcada9 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -1006,11 +1006,6 @@ struct kset *bus_get_kset(struct bus_type *bus) } EXPORT_SYMBOL_GPL(bus_get_kset); -static struct klist *bus_get_device_klist(struct bus_type *bus) -{ - return &bus->p->klist_devices; -} - /* * Yes, this forcibly breaks the klist abstraction temporarily. It * just wants to sort the klist, not change reference counts and @@ -1042,13 +1037,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) { @@ -1058,6 +1056,7 @@ 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); From adc18506941dcafe216aba80766ab51c890358e8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:23 +0100 Subject: [PATCH 102/124] driver core: move driver_find() to bus.c This function really is a bus function, not a driver one, so move it from driver.c to bus.c so that we can clean up some internal bus logic easier. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-15-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 27 +++++++++++++++++++++++++++ drivers/base/driver.c | 27 --------------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 87c44661dcada9..1040c724e50ca9 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -1288,6 +1288,33 @@ 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 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); + int __init buses_init(void) { bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 676b6275d5b536..aa5e5166a67197 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -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); From fb451966ae7d7e6d6802de39bda5fa2f15781244 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:24 +0100 Subject: [PATCH 103/124] driver core: bus: clean up driver_find() Convert the driver_find() function to use bus_to_subsys() and not use the back-pointer to the private structure. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-16-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 1040c724e50ca9..98edc7aa4fc4fd 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -1302,16 +1302,23 @@ EXPORT_SYMBOL_GPL(subsys_virtual_register); */ struct device_driver *driver_find(const char *name, struct bus_type *bus) { - struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); + struct subsys_private *sp = bus_to_subsys(bus); + struct kobject *k; 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; + 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); From 63b823d7d3cd275c3347233f95bdf966a595dbc8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:25 +0100 Subject: [PATCH 104/124] driver core: create bus_is_registered() A local function to the driver core to determine if a bus really is registered with the kernel or not. To be used only by the driver core code, as part of the driver registration path as it's not really "safe" because the bus could be unregistered instantly after being called. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-17-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 1 + drivers/base/bus.c | 16 ++++++++++++++++ drivers/base/driver.c | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 9e06c18c7a6442..726a12a244c061 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -146,6 +146,7 @@ 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); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 98edc7aa4fc4fd..c82c65fde8a1c4 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -1322,6 +1322,22 @@ struct device_driver *driver_find(const char *name, struct bus_type *bus) } 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; +} + int __init buses_init(void) { bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index aa5e5166a67197..c8436c26ed6ab3 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; From d2bf38c088e0d5467a0e8a2055d6f95dff5c2125 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:26 +0100 Subject: [PATCH 105/124] driver core: remove private pointer from struct bus_type Now that the driver code has been refactored to not rely on the pointer from a struct bus_type to the private structure it can be safely removed from the structure entirely. This will allow most bus_type structures to now be marked as const. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-18-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 4 ---- include/linux/device/bus.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c82c65fde8a1c4..719cd3a1354ca5 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -205,11 +205,9 @@ 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 const struct kobj_type bus_ktype = { @@ -854,7 +852,6 @@ int bus_register(struct bus_type *bus) return -ENOMEM; priv->bus = bus; - bus->p = priv; BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier); @@ -917,7 +914,6 @@ int bus_register(struct bus_type *bus) kset_unregister(&priv->subsys); out: kfree(priv); - bus->p = NULL; return retval; } EXPORT_SYMBOL_GPL(bus_register); diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index f6537f5fc53538..22bf6346927556 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. @@ -111,8 +109,6 @@ struct bus_type { const struct iommu_ops *iommu_ops; - struct subsys_private *p; - bool need_parent_lock; }; From bc8b7931012f0511f016e2f048d1f4222db8e08f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:27 +0100 Subject: [PATCH 106/124] driver core: bus: constify bus_register/unregister_notifier() The bus_register_notifier() and bus_unregister_notifier() functions should be taking a const * to bus_type, not just a * so fix that up. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-19-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 4 ++-- include/linux/device/bus.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 719cd3a1354ca5..0920fb117896c6 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -949,7 +949,7 @@ void bus_unregister(struct bus_type *bus) } 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) { struct subsys_private *sp = bus_to_subsys(bus); int retval; @@ -963,7 +963,7 @@ int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb) } 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) { struct subsys_private *sp = bus_to_subsys(bus); int retval; diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index 22bf6346927556..c0a034ff59b7e6 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -246,9 +246,9 @@ 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); /** From f91482be9b480dfce2616f5ba3fa548b8ed41efb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:28 +0100 Subject: [PATCH 107/124] driver core: bus: constify bus_get_kset() The bus_get_kset() function should be taking a const * to bus_type, not just a * so fix that up. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-20-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 +- include/linux/device/bus.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 0920fb117896c6..c394727b8253c1 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -987,7 +987,7 @@ void bus_notify(struct device *dev, enum bus_notifier_event value) subsys_put(sp); } -struct kset *bus_get_kset(struct bus_type *bus) +struct kset *bus_get_kset(const struct bus_type *bus) { struct subsys_private *sp = bus_to_subsys(bus); struct kset *kset; diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index c0a034ff59b7e6..425d79d6cf69b2 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -281,6 +281,6 @@ enum bus_notifier_event { BUS_NOTIFY_DRIVER_NOT_BOUND, }; -extern struct kset *bus_get_kset(struct bus_type *bus); +extern struct kset *bus_get_kset(const struct bus_type *bus); #endif From 4dd1f3f8f99ec51dbcfeffe95b8ab68161a332a4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:29 +0100 Subject: [PATCH 108/124] driver core: bus: constify some internal functions The functions add_probe_files() and remove_probe_files() should be taking a const * to bus_type, not just a *, so fix that up. These functions should really be removed entirely and an attribute group used instead, but for now, make this change so that other const work can continue. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-21-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c394727b8253c1..bcff24b11bb38f 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -603,7 +603,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; @@ -618,7 +618,7 @@ static int add_probe_files(struct bus_type *bus) 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); From ad8685d0f61a6fc1dc2e5874f4924ff5028c5954 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 8 Feb 2023 12:13:30 +0100 Subject: [PATCH 109/124] driver core: bus: constify bus_unregister() The bus_unregister() function can now take a const * to bus_type, not just a * so fix that up. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230208111330.439504-22-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 +- include/linux/device/bus.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index bcff24b11bb38f..301b9c6ece8649 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -925,7 +925,7 @@ 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; diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index 425d79d6cf69b2..31be18608f83f0 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -114,7 +114,7 @@ struct bus_type { 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); From 8c99377e614f8abfd881c34611002b2af5ab1ee8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 9 Feb 2023 10:35:56 +0100 Subject: [PATCH 110/124] driver core: bus: add bus_get_dev_root() function Instead of poking around in the struct bus_type directly for the dev_root pointer, provide a function to return it properly reference counted, if it is present in the bus. This will be needed to move the pointer out of struct bus_type in the future. Use the function in the driver core code at the same time it is introduced to verify that it works properly. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230209093556.19132-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 20 ++++++++++++++++++++ drivers/base/core.c | 14 +++++++++++--- drivers/base/cpu.c | 10 +++++++--- include/linux/device/bus.h | 1 + 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 301b9c6ece8649..def1e009ad9d58 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -1334,6 +1334,26 @@ bool bus_is_registered(const struct bus_type *bus) 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/core.c b/drivers/base/core.c index 2712a1a1e9590c..f9297c68214ae4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3173,8 +3173,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; @@ -3222,8 +3223,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; diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 441eb5bdec7d89..8bb623039bb2f0 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -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/include/linux/device/bus.h b/include/linux/device/bus.h index 31be18608f83f0..6ce32ef4b8fd49 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -282,5 +282,6 @@ enum bus_notifier_event { }; extern struct kset *bus_get_kset(const struct bus_type *bus); +struct device *bus_get_dev_root(const struct bus_type *bus); #endif From ccfc901f01170721554963745f7bd94c15235c96 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 10 Feb 2023 10:13:18 +0100 Subject: [PATCH 111/124] driver core: bus: update my copyright notice There's been some work done recently to the drivers/base/bus.c file so update the copyright notice in it to make those who track those types of things have an easier job. Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230210091318.733561-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index def1e009ad9d58..cfe8615d5106f0 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 * Copyright (c) 2007 Novell Inc. + * Copyright (c) 2023 Greg Kroah-Hartman */ #include From 31b4b6730fd4f5d503c9f23619c920ce7b794754 Mon Sep 17 00:00:00 2001 From: Longlong Xia Date: Fri, 10 Feb 2023 09:54:42 +0000 Subject: [PATCH 112/124] driver core: add error handling for devtmpfs_create_node() In some cases, devtmpfs_create_node() can return error value. So, make use of it. Signed-off-by: Longlong Xia Link: https://lore.kernel.org/r/20230210095444.4067307-2-xialonglong1@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index f9297c68214ae4..4fc6f27641bfca 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3602,7 +3602,9 @@ int device_add(struct device *dev) if (error) goto SysEntryError; - devtmpfs_create_node(dev); + error = devtmpfs_create_node(dev); + if (error) + goto DevtmpfsError; } /* Notify clients of device addition. This call must come @@ -3658,6 +3660,8 @@ int device_add(struct device *dev) done: put_device(dev); return error; + DevtmpfsError: + device_remove_sys_dev_entry(dev); SysEntryError: if (MAJOR(dev->devt)) device_remove_file(dev, &dev_attr_dev); From 90a9d5ff225267b3376f73c19f21174e3b6d7746 Mon Sep 17 00:00:00 2001 From: Longlong Xia Date: Fri, 10 Feb 2023 09:54:43 +0000 Subject: [PATCH 113/124] devtmpfs: add debug info to handle() Because handle() is the core function for processing devtmpfs requests, Let's add some debug info in handle() to help users know why failed. Signed-off-by: Longlong Xia Link: https://lore.kernel.org/r/20230210095444.4067307-3-xialonglong1@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 95ebc18ded5099..f273bccd549418 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -389,10 +389,18 @@ static __initdata DECLARE_COMPLETION(setup_done); static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid, struct device *dev) { + int ret; + if (mode) - return handle_create(name, mode, uid, gid, dev); + ret = handle_create(name, mode, uid, gid, dev); else - return handle_remove(name, dev); + ret = handle_remove(name, dev); + + if (ret) + dev_err(dev, "failed to %s %s, ret = %d\n", + mode ? "create" : "remove", name, ret); + + return ret; } static void __noreturn devtmpfs_work_loop(void) From 9d3fe6aa6b9517408064c7c3134187e8ec77dbf7 Mon Sep 17 00:00:00 2001 From: Longlong Xia Date: Fri, 10 Feb 2023 09:54:44 +0000 Subject: [PATCH 114/124] devtmpfs: remove return value of devtmpfs_delete_node() The only caller of device_del() does not check the return value. And there's nothing we can do when cleaning things up on a remove path. Let's make it a void function. Signed-off-by: Longlong Xia Link: https://lore.kernel.org/r/20230210095444.4067307-4-xialonglong1@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 4 ++-- drivers/base/devtmpfs.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 726a12a244c061..80cdf3fcb4581c 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -215,10 +215,10 @@ void device_pm_move_to_tail(struct device *dev); #ifdef CONFIG_DEVTMPFS int devtmpfs_create_node(struct device *dev); -int devtmpfs_delete_node(struct device *dev); +void devtmpfs_delete_node(struct device *dev); #else static inline int devtmpfs_create_node(struct device *dev) { return 0; } -static inline int devtmpfs_delete_node(struct device *dev) { return 0; } +static inline void devtmpfs_delete_node(struct device *dev) { } #endif void software_node_notify(struct device *dev); diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index f273bccd549418..a3a2657b9587e9 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -147,22 +147,22 @@ int devtmpfs_create_node(struct device *dev) return devtmpfs_submit_req(&req, tmp); } -int devtmpfs_delete_node(struct device *dev) +void devtmpfs_delete_node(struct device *dev) { const char *tmp = NULL; struct req req; if (!thread) - return 0; + return; req.name = device_get_devnode(dev, NULL, NULL, NULL, &tmp); if (!req.name) - return -ENOMEM; + return; req.mode = 0; req.dev = dev; - return devtmpfs_submit_req(&req, tmp); + devtmpfs_submit_req(&req, tmp); } static int dev_mkdir(const char *name, umode_t mode) From 2bc19066bda340540468ff88c2b1a798983bfd28 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 10 Feb 2023 11:24:08 +0100 Subject: [PATCH 115/124] driver core: cpu: don't hand-override the uevent bus_type callback. Instead of having to change the uevent bus_type callback by hand at runtime, set it at build time based on the build configuration options, making this much simpler to maintain and understand (and allow to make the structure constant.) Cc: "Rafael J. Wysocki" Link: https://lore.kernel.org/r/20230210102408.1083177-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/cpu.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 8bb623039bb2f0..182c6122f8152b 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 @@ -348,6 +337,20 @@ static int cpu_uevent(const 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; From d3583f06782cae72374464f9c29b2056fa0bd012 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 14 Feb 2023 08:59:13 +0100 Subject: [PATCH 116/124] Revert "devtmpfs: remove return value of devtmpfs_delete_node()" This reverts commit 9d3fe6aa6b9517408064c7c3134187e8ec77dbf7 as it is reported to cause boot regressions. Link: https://lore.kernel.org/r/Y+rSXg14z1Myd8Px@dev-arch.thelio-3990X Reported-by: Nathan Chancellor Cc: Longlong Xia Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 4 ++-- drivers/base/devtmpfs.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 80cdf3fcb4581c..726a12a244c061 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -215,10 +215,10 @@ void device_pm_move_to_tail(struct device *dev); #ifdef CONFIG_DEVTMPFS int devtmpfs_create_node(struct device *dev); -void devtmpfs_delete_node(struct device *dev); +int devtmpfs_delete_node(struct device *dev); #else static inline int devtmpfs_create_node(struct device *dev) { return 0; } -static inline void devtmpfs_delete_node(struct device *dev) { } +static inline int devtmpfs_delete_node(struct device *dev) { return 0; } #endif void software_node_notify(struct device *dev); diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index a3a2657b9587e9..f273bccd549418 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -147,22 +147,22 @@ int devtmpfs_create_node(struct device *dev) return devtmpfs_submit_req(&req, tmp); } -void devtmpfs_delete_node(struct device *dev) +int devtmpfs_delete_node(struct device *dev) { const char *tmp = NULL; struct req req; if (!thread) - return; + return 0; req.name = device_get_devnode(dev, NULL, NULL, NULL, &tmp); if (!req.name) - return; + return -ENOMEM; req.mode = 0; req.dev = dev; - devtmpfs_submit_req(&req, tmp); + return devtmpfs_submit_req(&req, tmp); } static int dev_mkdir(const char *name, umode_t mode) From 48c9899affd51f7acfc07a3f4d777b6eeb73a451 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 14 Feb 2023 08:59:22 +0100 Subject: [PATCH 117/124] Revert "devtmpfs: add debug info to handle()" This reverts commit 90a9d5ff225267b3376f73c19f21174e3b6d7746 as it is reported to cause boot regressions. Link: https://lore.kernel.org/r/Y+rSXg14z1Myd8Px@dev-arch.thelio-3990X Reported-by: Nathan Chancellor Cc: Longlong Xia Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index f273bccd549418..95ebc18ded5099 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -389,18 +389,10 @@ static __initdata DECLARE_COMPLETION(setup_done); static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid, struct device *dev) { - int ret; - if (mode) - ret = handle_create(name, mode, uid, gid, dev); + return handle_create(name, mode, uid, gid, dev); else - ret = handle_remove(name, dev); - - if (ret) - dev_err(dev, "failed to %s %s, ret = %d\n", - mode ? "create" : "remove", name, ret); - - return ret; + return handle_remove(name, dev); } static void __noreturn devtmpfs_work_loop(void) From 17c45768fdf970b8a2ea9745783ff6a0512fca11 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 14 Feb 2023 08:59:33 +0100 Subject: [PATCH 118/124] Revert "driver core: add error handling for devtmpfs_create_node()" This reverts commit 31b4b6730fd4f5d503c9f23619c920ce7b794754 as it is reported to cause boot regressions. Link: https://lore.kernel.org/r/Y+rSXg14z1Myd8Px@dev-arch.thelio-3990X Reported-by: Nathan Chancellor Cc: Longlong Xia Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 4fc6f27641bfca..f9297c68214ae4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3602,9 +3602,7 @@ int device_add(struct device *dev) if (error) goto SysEntryError; - error = devtmpfs_create_node(dev); - if (error) - goto DevtmpfsError; + devtmpfs_create_node(dev); } /* Notify clients of device addition. This call must come @@ -3660,8 +3658,6 @@ int device_add(struct device *dev) done: put_device(dev); return error; - DevtmpfsError: - device_remove_sys_dev_entry(dev); SysEntryError: if (MAJOR(dev->devt)) device_remove_file(dev, &dev_attr_dev); From 779aeb73d925586945b5dacab7453824766f149d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 14 Feb 2023 15:41:17 +0100 Subject: [PATCH 119/124] driver core: class: move EXPORT_SYMBOL_GPL() lines to the correct place For some reason, the drivers/base/class.c file still had the "old style" of exports, at the end of the file. Move the exports to the proper location, right after the function, to be correct. Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20230214144117.158956-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/base/class.c b/drivers/base/class.c index 89d4528fcc1a98..2373b3e210d897 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -99,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) @@ -106,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) { @@ -213,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) { @@ -276,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 @@ -460,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) { @@ -482,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) @@ -588,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); From ade1229caed9433921b69e20bd6fadf1bba9558e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 14 Feb 2023 15:01:21 +0100 Subject: [PATCH 120/124] dma-mapping: no need to pass a bus_type into get_arch_dma_ops() The get_arch_dma_ops() arch-specific function never does anything with the struct bus_type that is passed into it, so remove it entirely as it is not needed. Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Cc: Thomas Bogendoerfer Cc: "James E.J. Bottomley" Cc: Helge Deller Cc: "David S. Miller" Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: x86@kernel.org Cc: "H. Peter Anvin" Cc: Marek Szyprowski Cc: Robin Murphy Cc: Konrad Rzeszutek Wilk Cc: linux-alpha@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-mips@vger.kernel.org Cc: linux-parisc@vger.kernel.org Cc: sparclinux@vger.kernel.org Cc: iommu@lists.linux.dev Cc: linux-arch@vger.kernel.org Acked-by: Christoph Hellwig Reviewed-by: Arnd Bergmann Link: https://lore.kernel.org/r/20230214140121.131859-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- arch/alpha/include/asm/dma-mapping.h | 2 +- arch/ia64/include/asm/dma-mapping.h | 2 +- arch/mips/include/asm/dma-mapping.h | 2 +- arch/parisc/include/asm/dma-mapping.h | 2 +- arch/sparc/include/asm/dma-mapping.h | 2 +- arch/x86/include/asm/dma-mapping.h | 2 +- include/asm-generic/dma-mapping.h | 2 +- include/linux/dma-map-ops.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/alpha/include/asm/dma-mapping.h b/arch/alpha/include/asm/dma-mapping.h index 0ee6a5c99b16b5..6ce7e2041685b3 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/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h index a5d9d788eede1f..af6fa8e1597c6e 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 34de7b17b41b72..0fee561ac7966a 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/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h index d5bd94247371e0..635665004fe66d 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/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h index 2f051343612e8a..55c12fc2ba63b5 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/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 1c66708e306235..d1dac96ee30b6c 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/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h index c13f46109e8883..46a0016efd8148 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/linux/dma-map-ops.h b/include/linux/dma-map-ops.h index d678afeb8a13a3..41bf4bdb117acc 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, From 007ed7900aae514986770f6e14069ebd99c4a4c6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 12 Feb 2023 23:03:24 -0800 Subject: [PATCH 121/124] i3c: fix device.h kernel-doc warnings Fix all kernel-doc warnings in : include/linux/i3c/device.h:27: warning: contents before sections include/linux/i3c/device.h:196: warning: Excess function parameter 'dev' description in 'dev_to_i3cdev' Fixes: fa838c8ce537 ("i3c: move dev_to_i3cdev() to use container_of_const()") Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure") Signed-off-by: Randy Dunlap Cc: Boris Brezillon Cc: Greg Kroah-Hartman Cc: Alexandre Belloni Cc: linux-i3c@lists.infradead.org Link: https://lore.kernel.org/r/20230213070324.1564-1-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- include/linux/i3c/device.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h index ce115ef08fec2d..90fa83464f0039 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, @@ -189,7 +190,7 @@ struct device *i3cdev_to_dev(struct i3c_device *i3cdev); /** * dev_to_i3cdev() - Returns the I3C device containing @dev - * @dev: device object + * @__dev: device object * * Return: a pointer to an I3C device object. */ From d3002468cb5d5da11e22145c9af32facd5c34352 Mon Sep 17 00:00:00 2001 From: Qi Zheng Date: Wed, 8 Feb 2023 11:56:34 +0800 Subject: [PATCH 122/124] debugfs: update comment of debugfs_rename() Since commit ff9fb72bc077 ("debugfs: return error values, not NULL") changed return value of debugfs_rename() in error cases from %NULL to %ERR_PTR(-ERROR), the comment of debugfs_rename should also be updated so as not to mislead readers. Signed-off-by: Qi Zheng Link: https://lore.kernel.org/r/20230208035634.58095-1-zhengqi.arch@bytedance.com Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 2e8e112b19930d..58a35afb7c5d89 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. From 9f467f6375afd3c7667dbabcfff35c22961e1c0b Mon Sep 17 00:00:00 2001 From: Qi Zheng Date: Wed, 8 Feb 2023 12:00:37 +0800 Subject: [PATCH 123/124] OPP: fix error checking in opp_migrate_dentry() Since commit ff9fb72bc077 ("debugfs: return error values, not NULL") changed return value of debugfs_rename() in error cases from %NULL to %ERR_PTR(-ERROR), we should also check error values instead of NULL. Fixes: ff9fb72bc077 ("debugfs: return error values, not NULL") Signed-off-by: Qi Zheng Link: https://lore.kernel.org/r/20230208040037.60305-1-zhengqi.arch@bytedance.com Signed-off-by: Greg Kroah-Hartman --- drivers/opp/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c index 96a30a032c5f99..2c7fb683441eff 100644 --- a/drivers/opp/debugfs.c +++ b/drivers/opp/debugfs.c @@ -235,7 +235,7 @@ static void opp_migrate_dentry(struct opp_device *opp_dev, dentry = debugfs_rename(rootdir, opp_dev->dentry, rootdir, opp_table->dentry_name); - if (!dentry) { + if (IS_ERR(dentry)) { dev_err(dev, "%s: Failed to rename link from: %s to %s\n", __func__, dev_name(opp_dev->dev), dev_name(dev)); return; From 88cd618dcc7b63baa1478730b02eaba3e3148467 Mon Sep 17 00:00:00 2001 From: Bagas Sanjaya Date: Mon, 20 Feb 2023 19:47:21 +0700 Subject: [PATCH 124/124] debugfs: drop inline constant formatting for ERR_PTR(-ERROR) Stephen Rothwell reported htmldocs warning when merging driver-core tree for linux-next: Documentation/filesystems/api-summary:146: fs/debugfs/inode.c:804: WARNING: Inline literal start-string without end-string. The warning is due to inline constant formatting (``%CONST``) doesn't play nice with complex-name constants like ERR_PTR(-ERROR). Drop the formatting for that constant above to be consistent with similar error constants and also to fix the above warning. Link: https://lore.kernel.org/lkml/20230220163133.481e43d8@canb.auug.org.au/ Fixes: d3002468cb5d5d ("debugfs: update comment of debugfs_rename()") Reported-by: Stephen Rothwell Signed-off-by: Bagas Sanjaya Link: https://lore.kernel.org/r/20230220124721.11657-1-bagasdotme@gmail.com Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 58a35afb7c5d89..a7a6a0821605a8 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -802,7 +802,7 @@ 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, %ERR_PTR(-ERROR) + * 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