From 901cff7cb96140a658a848a568b606ba764239bc Mon Sep 17 00:00:00 2001 From: Topi Miettinen Date: Thu, 23 Jan 2020 14:58:38 +0200 Subject: firmware_loader: load files from the mount namespace of init I have an experimental setup where almost every possible system service (even early startup ones) runs in separate namespace, using a dedicated, minimal file system. In process of minimizing the contents of the file systems with regards to modules and firmware files, I noticed that in my system, the firmware files are loaded from three different mount namespaces, those of systemd-udevd, init and systemd-networkd. The logic of the source namespace is not very clear, it seems to depend on the driver, but the namespace of the current process is used. So, this patch tries to make things a bit clearer and changes the loading of firmware files only from the mount namespace of init. This may also improve security, though I think that using firmware files as attack vector could be too impractical anyway. Later, it might make sense to make the mount namespace configurable, for example with a new file in /proc/sys/kernel/firmware_config/. That would allow a dedicated file system only for firmware files and those need not be present anywhere else. This configurability would make more sense if made also for kernel modules and /sbin/modprobe. Modules are already loaded from init namespace (usermodehelper uses kthreadd namespace) except when directly loaded by systemd-udevd. Instead of using the mount namespace of the current process to load firmware files, use the mount namespace of init process. Link: https://lore.kernel.org/lkml/bb46ebae-4746-90d9-ec5b-fce4c9328c86@gmail.com/ Link: https://lore.kernel.org/lkml/0e3f7653-c59d-9341-9db2-c88f5b988c68@gmail.com/ Signed-off-by: Topi Miettinen Link: https://lore.kernel.org/r/20200123125839.37168-1-toiwoton@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_loader/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 57133a9dad09..59d1dc322080 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -493,8 +493,10 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv, } fw_priv->size = 0; - rc = kernel_read_file_from_path(path, &buffer, &size, - msize, id); + + /* load firmware files from the mount namespace of init */ + rc = kernel_read_file_from_path_initns(path, &buffer, + &size, msize, id); if (rc) { if (rc != -ENOENT) dev_warn(device, "loading %s failed with error %d\n", -- cgit v1.2.3 From 1745d299af5b373abad08fa29bff0d31dc6aff21 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Fri, 21 Feb 2020 17:40:34 -0800 Subject: driver core: Reevaluate dev->links.need_for_probe as suppliers are added A previous patch 03324507e66c ("driver core: Allow fwnode_operations.add_links to differentiate errors") forgot to update all call sites to fwnode_operations.add_links. This patch fixes that. Legend: -> Denotes RHS is an optional/potential supplier for LHS => Denotes RHS is a mandatory supplier for LHS Example: Device A => Device X Device A -> Device Y Before this patch: 1. Device A is added. 2. Device A is marked as waiting for mandatory suppliers 3. Device X is added 4. Device A is left marked as waiting for mandatory suppliers Step 4 is wrong since all mandatory suppliers of Device A have been added. After this patch: 1. Device A is added. 2. Device A is marked as waiting for mandatory suppliers 3. Device X is added 4. Device A is no longer considered as waiting for mandatory suppliers This is the correct behavior. Fixes: 03324507e66c ("driver core: Allow fwnode_operations.add_links to differentiate errors") Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20200222014038.180923-2-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 42a672456432..79863354c801 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -523,9 +523,13 @@ static void device_link_add_missing_supplier_links(void) mutex_lock(&wfs_lock); list_for_each_entry_safe(dev, tmp, &wait_for_suppliers, - links.needs_suppliers) - if (!fwnode_call_int_op(dev->fwnode, add_links, dev)) + links.needs_suppliers) { + int ret = fwnode_call_int_op(dev->fwnode, add_links, dev); + if (!ret) list_del_init(&dev->links.needs_suppliers); + else if (ret != -ENODEV) + dev->links.need_for_probe = false; + } mutex_unlock(&wfs_lock); } -- cgit v1.2.3 From 8375e74f2bca9802a4ddf431a6d7bd2ab9950f27 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Fri, 21 Feb 2020 17:40:35 -0800 Subject: driver core: Add fw_devlink kernel commandline option fwnode_operations.add_links allows creating device links from information provided by firmware. fwnode_operations.add_links is currently implemented only by OF/devicetree code and a specific case of efi. However, there's nothing preventing ACPI or other firmware types from implementing it. The OF implementation is currently controlled by a kernel commandline parameter called of_devlink. Since this feature is generic isn't limited to OF, add a generic fw_devlink kernel commandline parameter to control this feature across firmware types. Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20200222014038.180923-3-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- Documentation/admin-guide/kernel-parameters.txt | 18 +++++++++++++++++ drivers/base/core.c | 27 ++++++++++++++++++++++++- include/linux/fwnode.h | 2 ++ 3 files changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index dbc22d684627..29985152b66d 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1350,6 +1350,24 @@ can be changed at run time by the max_graph_depth file in the tracefs tracing directory. default: 0 (no limit) + fw_devlink= [KNL] Create device links between consumer and supplier + devices by scanning the firmware to infer the + consumer/supplier relationships. This feature is + especially useful when drivers are loaded as modules as + it ensures proper ordering of tasks like device probing + (suppliers first, then consumers), supplier boot state + clean up (only after all consumers have probed), + suspend/resume & runtime PM (consumers first, then + suppliers). + Format: { off | permissive | on | rpm } + off -- Don't create device links from firmware info. + permissive -- Create device links from firmware info + but use it only for ordering boot state clean + up (sync_state() calls). + on -- Create device links from firmware info and use it + to enforce probe and suspend/resume ordering. + rpm -- Like "on", but also use to order runtime PM. + gamecon.map[2|3]= [HW,JOY] Multisystem joystick and NES/SNES/PSX pad support via parallel port (up to 5 devices per port) diff --git a/drivers/base/core.c b/drivers/base/core.c index 79863354c801..922680af9051 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2332,6 +2332,31 @@ static int device_private_init(struct device *dev) return 0; } +u32 fw_devlink_flags; +static int __init fw_devlink_setup(char *arg) +{ + if (!arg) + return -EINVAL; + + if (strcmp(arg, "off") == 0) { + fw_devlink_flags = 0; + } else if (strcmp(arg, "permissive") == 0) { + fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY; + } else if (strcmp(arg, "on") == 0) { + fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER; + } else if (strcmp(arg, "rpm") == 0) { + fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER | + DL_FLAG_PM_RUNTIME; + } + return 0; +} +early_param("fw_devlink", fw_devlink_setup); + +u32 fw_devlink_get_flags(void) +{ + return fw_devlink_flags; +} + /** * device_add - add device to device hierarchy. * @dev: device. @@ -2480,7 +2505,7 @@ int device_add(struct device *dev) */ device_link_add_missing_supplier_links(); - if (fwnode_has_op(dev->fwnode, add_links)) { + if (fw_devlink_flags && fwnode_has_op(dev->fwnode, add_links)) { fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev); if (fw_ret == -ENODEV) device_link_wait_for_mandatory_supplier(dev); diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 8feeb94b8acc..e0abafbb17f8 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -170,4 +170,6 @@ struct fwnode_operations { } while (false) #define get_dev_from_fwnode(fwnode) get_device((fwnode)->dev) +extern u32 fw_devlink_get_flags(void); + #endif -- cgit v1.2.3 From c8c43cee29f6ca2575c953ae600263690db28f41 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 25 Feb 2020 05:08:23 +0000 Subject: driver core: Fix driver_deferred_probe_check_state() logic driver_deferred_probe_check_state() has some uninituitive behavior. * From boot to late_initcall, it returns -EPROBE_DEFER * From late_initcall to the deferred_probe_timeout (if set) it returns -ENODEV * If the deferred_probe_timeout it set, after it fires, it returns -ETIMEDOUT This is a bit confusing, as its useful to have the function return -EPROBE_DEFER while the timeout is still running. This behavior has resulted in the somwhat duplicative driver_deferred_probe_check_state_continue() function being added. Thus this patch tries to improve the logic, so that it behaves as such: * If late_initcall has passed, and modules are not enabled it returns -ENODEV * If modules are enabled and deferred_probe_timeout is set, it returns -EPROBE_DEFER until the timeout, afterwhich it returns -ETIMEDOUT. * In all other cases, it returns -EPROBE_DEFER This will make the deferred_probe_timeout value much more functional, and will allow us to consolidate the driver_deferred_probe_check_state() and driver_deferred_probe_check_state_continue() logic in a later patch. Cc: linux-pm@vger.kernel.org Cc: Greg Kroah-Hartman Cc: Linus Walleij Cc: Thierry Reding Cc: Mark Brown Cc: Liam Girdwood Cc: Bjorn Andersson Cc: Saravana Kannan Cc: Todd Kjos Cc: Len Brown Cc: Pavel Machek Cc: Ulf Hansson Cc: Kevin Hilman Cc: "Rafael J. Wysocki" Cc: Rob Herring Signed-off-by: John Stultz Link: https://lore.kernel.org/r/20200225050828.56458-2-john.stultz@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index b25bcab2a26b..d75b34de6964 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -237,24 +237,26 @@ __setup("deferred_probe_timeout=", deferred_probe_timeout_setup); static int __driver_deferred_probe_check_state(struct device *dev) { - if (!initcalls_done) - return -EPROBE_DEFER; + if (!IS_ENABLED(CONFIG_MODULES) && initcalls_done) + return -ENODEV; if (!deferred_probe_timeout) { dev_WARN(dev, "deferred probe timeout, ignoring dependency"); return -ETIMEDOUT; } - return 0; + return -EPROBE_DEFER; } /** * driver_deferred_probe_check_state() - Check deferred probe state * @dev: device to check * - * Returns -ENODEV if init is done and all built-in drivers have had a chance - * to probe (i.e. initcalls are done), -ETIMEDOUT if deferred probe debug - * timeout has expired, or -EPROBE_DEFER if none of those conditions are met. + * Return: + * -ENODEV if initcalls have completed and modules are disabled. + * -ETIMEDOUT if the deferred probe timeout was set and has expired + * and modules are enabled. + * -EPROBE_DEFER in other cases. * * Drivers or subsystems can opt-in to calling this function instead of directly * returning -EPROBE_DEFER. @@ -264,7 +266,7 @@ int driver_deferred_probe_check_state(struct device *dev) int ret; ret = __driver_deferred_probe_check_state(dev); - if (ret < 0) + if (ret != -ENODEV) return ret; dev_warn(dev, "ignoring dependency for device, assuming no driver"); @@ -292,7 +294,7 @@ int driver_deferred_probe_check_state_continue(struct device *dev) int ret; ret = __driver_deferred_probe_check_state(dev); - if (ret < 0) + if (ret != -ENODEV) return ret; return -EPROBE_DEFER; -- cgit v1.2.3 From e2cec7d6853712295cef5377762165a489b2957f Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 25 Feb 2020 05:08:24 +0000 Subject: driver core: Set deferred_probe_timeout to a longer default if CONFIG_MODULES is set When using modules, its common for the modules not to be loaded until quite late by userland. With the current code, driver_deferred_probe_check_state() will stop returning EPROBE_DEFER after late_initcall, which can cause module dependency resolution to fail after that. So allow a longer window of 30 seconds (picked somewhat arbitrarily, but influenced by the similar regulator core timeout value) in the case where modules are enabled. Cc: linux-pm@vger.kernel.org Cc: Greg Kroah-Hartman Cc: Linus Walleij Cc: Thierry Reding Cc: Mark Brown Cc: Liam Girdwood Cc: Bjorn Andersson Cc: Saravana Kannan Cc: Todd Kjos Cc: Len Brown Cc: Pavel Machek Cc: Ulf Hansson Cc: Kevin Hilman Cc: "Rafael J. Wysocki" Cc: Rob Herring Reviewed-by: Bjorn Andersson Reviewed-by: Rafael J. Wysocki Signed-off-by: John Stultz Link: https://lore.kernel.org/r/20200225050828.56458-3-john.stultz@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index d75b34de6964..fe26f2574a6d 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -224,7 +224,16 @@ static int deferred_devs_show(struct seq_file *s, void *data) } DEFINE_SHOW_ATTRIBUTE(deferred_devs); +#ifdef CONFIG_MODULES +/* + * In the case of modules, set the default probe timeout to + * 30 seconds to give userland some time to load needed modules + */ +static int deferred_probe_timeout = 30; +#else +/* In the case of !modules, no probe timeout needed */ static int deferred_probe_timeout = -1; +#endif static int __init deferred_probe_timeout_setup(char *str) { int timeout; -- cgit v1.2.3 From 0e9f8d09d2806aa2e10a04a78f82544e4ee737a1 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 25 Feb 2020 05:08:26 +0000 Subject: driver core: Remove driver_deferred_probe_check_state_continue() Now that driver_deferred_probe_check_state() works better, and we've converted the only user of driver_deferred_probe_check_state_continue() we can simply remove it and simplify some of the logic. Cc: linux-pm@vger.kernel.org Cc: Greg Kroah-Hartman Cc: Linus Walleij Cc: Thierry Reding Cc: Mark Brown Cc: Liam Girdwood Cc: Bjorn Andersson Cc: Saravana Kannan Cc: Todd Kjos Cc: Len Brown Cc: Pavel Machek Cc: Ulf Hansson Cc: Kevin Hilman Cc: "Rafael J. Wysocki" Cc: Rob Herring Reviewed-by: Bjorn Andersson Reviewed-by: Rafael J. Wysocki Signed-off-by: John Stultz Link: https://lore.kernel.org/r/20200225050828.56458-5-john.stultz@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 53 +++++++------------------------------------ include/linux/device/driver.h | 1 - 2 files changed, 8 insertions(+), 46 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index fe26f2574a6d..c09e4e7277d4 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -244,19 +244,6 @@ static int __init deferred_probe_timeout_setup(char *str) } __setup("deferred_probe_timeout=", deferred_probe_timeout_setup); -static int __driver_deferred_probe_check_state(struct device *dev) -{ - if (!IS_ENABLED(CONFIG_MODULES) && initcalls_done) - return -ENODEV; - - if (!deferred_probe_timeout) { - dev_WARN(dev, "deferred probe timeout, ignoring dependency"); - return -ETIMEDOUT; - } - - return -EPROBE_DEFER; -} - /** * driver_deferred_probe_check_state() - Check deferred probe state * @dev: device to check @@ -272,39 +259,15 @@ static int __driver_deferred_probe_check_state(struct device *dev) */ int driver_deferred_probe_check_state(struct device *dev) { - int ret; - - ret = __driver_deferred_probe_check_state(dev); - if (ret != -ENODEV) - return ret; - - dev_warn(dev, "ignoring dependency for device, assuming no driver"); - - return -ENODEV; -} - -/** - * driver_deferred_probe_check_state_continue() - check deferred probe state - * @dev: device to check - * - * Returns -ETIMEDOUT if deferred probe debug timeout has expired, or - * -EPROBE_DEFER otherwise. - * - * Drivers or subsystems can opt-in to calling this function instead of - * directly returning -EPROBE_DEFER. - * - * This is similar to driver_deferred_probe_check_state(), but it allows the - * subsystem to keep deferring probe after built-in drivers have had a chance - * to probe. One scenario where that is useful is if built-in drivers rely on - * resources that are provided by modular drivers. - */ -int driver_deferred_probe_check_state_continue(struct device *dev) -{ - int ret; + if (!IS_ENABLED(CONFIG_MODULES) && initcalls_done) { + dev_warn(dev, "ignoring dependency for device, assuming no driver"); + return -ENODEV; + } - ret = __driver_deferred_probe_check_state(dev); - if (ret != -ENODEV) - return ret; + if (!deferred_probe_timeout) { + dev_WARN(dev, "deferred probe timeout, ignoring dependency"); + return -ETIMEDOUT; + } return -EPROBE_DEFER; } diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index 1188260f9a02..5242afabfaba 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -238,7 +238,6 @@ driver_find_device_by_acpi_dev(struct device_driver *drv, const void *adev) void driver_deferred_probe_add(struct device *dev); int driver_deferred_probe_check_state(struct device *dev); -int driver_deferred_probe_check_state_continue(struct device *dev); void driver_init(void); /** -- cgit v1.2.3 From 64c775fb4b21ab2532555e833edf52055df5fb1c Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 25 Feb 2020 05:08:27 +0000 Subject: driver core: Rename deferred_probe_timeout and make it global Since other subsystems (like regulator) have similar arbitrary timeouts for how long they try to resolve driver dependencies, rename deferred_probe_timeout to driver_deferred_probe_timeout and set it as global, so it can be shared. Cc: linux-pm@vger.kernel.org Cc: Greg Kroah-Hartman Cc: Linus Walleij Cc: Thierry Reding Cc: Mark Brown Cc: Liam Girdwood Cc: Bjorn Andersson Cc: Saravana Kannan Cc: Todd Kjos Cc: Len Brown Cc: Pavel Machek Cc: Ulf Hansson Cc: Kevin Hilman Cc: "Rafael J. Wysocki" Cc: Rob Herring Reviewed-by: Bjorn Andersson Reviewed-by: Rafael J. Wysocki Signed-off-by: John Stultz Link: https://lore.kernel.org/r/20200225050828.56458-6-john.stultz@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 16 +++++++++------- include/linux/device/driver.h | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index c09e4e7277d4..76888a7459d8 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -229,17 +229,19 @@ DEFINE_SHOW_ATTRIBUTE(deferred_devs); * In the case of modules, set the default probe timeout to * 30 seconds to give userland some time to load needed modules */ -static int deferred_probe_timeout = 30; +int driver_deferred_probe_timeout = 30; #else /* In the case of !modules, no probe timeout needed */ -static int deferred_probe_timeout = -1; +int driver_deferred_probe_timeout = -1; #endif +EXPORT_SYMBOL_GPL(driver_deferred_probe_timeout); + static int __init deferred_probe_timeout_setup(char *str) { int timeout; if (!kstrtoint(str, 10, &timeout)) - deferred_probe_timeout = timeout; + driver_deferred_probe_timeout = timeout; return 1; } __setup("deferred_probe_timeout=", deferred_probe_timeout_setup); @@ -264,7 +266,7 @@ int driver_deferred_probe_check_state(struct device *dev) return -ENODEV; } - if (!deferred_probe_timeout) { + if (!driver_deferred_probe_timeout) { dev_WARN(dev, "deferred probe timeout, ignoring dependency"); return -ETIMEDOUT; } @@ -276,7 +278,7 @@ static void deferred_probe_timeout_work_func(struct work_struct *work) { struct device_private *private, *p; - deferred_probe_timeout = 0; + driver_deferred_probe_timeout = 0; driver_deferred_probe_trigger(); flush_work(&deferred_probe_work); @@ -310,9 +312,9 @@ static int deferred_probe_initcall(void) driver_deferred_probe_trigger(); flush_work(&deferred_probe_work); - if (deferred_probe_timeout > 0) { + if (driver_deferred_probe_timeout > 0) { schedule_delayed_work(&deferred_probe_timeout_work, - deferred_probe_timeout * HZ); + driver_deferred_probe_timeout * HZ); } return 0; } diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index 5242afabfaba..ee7ba5b5417e 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -236,6 +236,7 @@ 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); -- cgit v1.2.3 From ab7789c5174cb12c9f9fb4f85efc6d18e7f04c2b Mon Sep 17 00:00:00 2001 From: Jules Irenge Date: Fri, 14 Feb 2020 20:47:30 +0000 Subject: driver core: Add missing annotation for device_links_read_lock() Sparse reports a warning at device_links_read_unlock() warning: warning: context imbalance in device_links_read_unlock() - unexpected unlock The root cause is the missing annotation at device_links_read_unlock() Add the missing __releases(&device_links_srcu) annotation Signed-off-by: Jules Irenge Link: https://lore.kernel.org/r/20200214204741.94112-20-jbi.octave@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 922680af9051..ae6804da67b2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -69,7 +69,7 @@ int device_links_read_lock(void) return srcu_read_lock(&device_links_srcu); } -void device_links_read_unlock(int idx) +void device_links_read_unlock(int idx) __releases(&device_links_srcu) { srcu_read_unlock(&device_links_srcu, idx); } -- cgit v1.2.3 From 68464d79015a1bbb41872a9119a07b2cb151a4b9 Mon Sep 17 00:00:00 2001 From: Jules Irenge Date: Fri, 14 Feb 2020 20:47:29 +0000 Subject: driver core: Add missing annotation for device_links_write_lock() Sparse reports a warning at device_links_write_lock() warning: context imbalance in evice_links_write_lock() - wrong count at exit The root cause is the missing annotation at device_links_write_lock() Add the missing __acquires(&device_links_srcu) annotation Signed-off-by: Jules Irenge Link: https://lore.kernel.org/r/20200214204741.94112-19-jbi.octave@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index ae6804da67b2..26acb92aa966 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -64,7 +64,7 @@ static inline void device_links_write_unlock(void) mutex_unlock(&device_links_lock); } -int device_links_read_lock(void) +int device_links_read_lock(void) __acquires(&device_links_srcu) { return srcu_read_lock(&device_links_srcu); } -- cgit v1.2.3 From 9211f0a6a91ada1ee28b3fb5f30d79c8a67c73b1 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 5 Mar 2020 10:09:24 +0800 Subject: driver core: fw_devlink_flags can be static Fixes: 8375e74f2bca ("driver core: Add fw_devlink kernel commandline option") Signed-off-by: kbuild test robot Acked-by: Saravana Kannan Link: https://lore.kernel.org/r/20200305020916.GA14234@3143ef58ba07 Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 26acb92aa966..cd78a001d719 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2332,7 +2332,7 @@ static int device_private_init(struct device *dev) return 0; } -u32 fw_devlink_flags; +static u32 fw_devlink_flags; static int __init fw_devlink_setup(char *arg) { if (!arg) -- cgit v1.2.3 From 4636a04630f632262e915f62deb59fa0f3ee5186 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Mar 2020 09:02:06 +0100 Subject: drivers/base/cpu: Use scnprintf() for avoiding potential buffer overflow Since snprintf() returns the would-be-output size instead of the actual output size, the succeeding calls may go beyond the given buffer limit. Fix it by replacing with scnprintf(). Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20200311080207.12046-2-tiwai@suse.de Signed-off-by: Greg Kroah-Hartman --- drivers/base/cpu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 6265871a4af2..67aaa052c7a2 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -258,13 +258,13 @@ static ssize_t print_cpus_offline(struct device *dev, buf[n++] = ','; if (nr_cpu_ids == total_cpus-1) - n += snprintf(&buf[n], len - n, "%u", nr_cpu_ids); + n += scnprintf(&buf[n], len - n, "%u", nr_cpu_ids); else - n += snprintf(&buf[n], len - n, "%u-%d", + n += scnprintf(&buf[n], len - n, "%u-%d", nr_cpu_ids, total_cpus-1); } - n += snprintf(&buf[n], len - n, "\n"); + n += scnprintf(&buf[n], len - n, "\n"); return n; } static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); -- cgit v1.2.3 From 847e33867b65fdc4747a15646d1fdb94e65740a6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Mar 2020 09:02:07 +0100 Subject: drivers/base/cpu: Simplify s*nprintf() usages Use the simpler sprintf() instead of snprintf() or scnprintf() in a single-shot sysfs output callbacks where you are very sure that it won't go over PAGE_SIZE buffer limit. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20200311080207.12046-3-tiwai@suse.de Signed-off-by: Greg Kroah-Hartman --- drivers/base/cpu.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 67aaa052c7a2..df19c002d747 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -231,8 +231,7 @@ static struct cpu_attr cpu_attrs[] = { static ssize_t print_cpus_kernel_max(struct device *dev, struct device_attribute *attr, char *buf) { - int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); - return n; + return sprintf(buf, "%d\n", NR_CPUS - 1); } static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); @@ -272,7 +271,7 @@ static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); static ssize_t print_cpus_isolated(struct device *dev, struct device_attribute *attr, char *buf) { - int n = 0, len = PAGE_SIZE-2; + int n; cpumask_var_t isolated; if (!alloc_cpumask_var(&isolated, GFP_KERNEL)) @@ -280,7 +279,7 @@ static ssize_t print_cpus_isolated(struct device *dev, cpumask_andnot(isolated, cpu_possible_mask, housekeeping_cpumask(HK_FLAG_DOMAIN)); - n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(isolated)); + n = sprintf(buf, "%*pbl\n", cpumask_pr_args(isolated)); free_cpumask_var(isolated); @@ -292,11 +291,7 @@ static DEVICE_ATTR(isolated, 0444, print_cpus_isolated, NULL); static ssize_t print_cpus_nohz_full(struct device *dev, struct device_attribute *attr, char *buf) { - int n = 0, len = PAGE_SIZE-2; - - n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask)); - - return n; + return sprintf(buf, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask)); } static DEVICE_ATTR(nohz_full, 0444, print_cpus_nohz_full, NULL); #endif -- cgit v1.2.3 From b8fe128dad8f97cc9af7c55a264d1fc5ab677195 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Mon, 13 Jan 2020 11:48:15 +0800 Subject: arch_topology: Adjust initial CPU capacities with current freq The CPU freqs are not supposed to change before cpufreq policies properly registered, meaning that they should be used to calculate the initial CPU capacities. Doing this helps choosing the best CPU during early boot, especially for the initramfs decompressing. There's no functional changes for non-clk CPU DVFS mechanism. Signed-off-by: Jeffy Chen Link: https://lore.kernel.org/r/20200113034815.25924-1-jeffy.chen@rock-chips.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/arch_topology.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 6119e11a9f95..b56c33e5b6a8 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -94,7 +94,7 @@ static void update_topology_flags_workfn(struct work_struct *work) update_topology = 0; } -static u32 capacity_scale; +static DEFINE_PER_CPU(u32, freq_factor) = 1; static u32 *raw_capacity; static int free_raw_capacity(void) @@ -108,17 +108,23 @@ static int free_raw_capacity(void) void topology_normalize_cpu_scale(void) { u64 capacity; + u64 capacity_scale; int cpu; if (!raw_capacity) return; - pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale); + capacity_scale = 1; for_each_possible_cpu(cpu) { - pr_debug("cpu_capacity: cpu=%d raw_capacity=%u\n", - cpu, raw_capacity[cpu]); - capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT) - / capacity_scale; + capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu); + capacity_scale = max(capacity, capacity_scale); + } + + pr_debug("cpu_capacity: capacity_scale=%llu\n", capacity_scale); + for_each_possible_cpu(cpu) { + capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu); + capacity = div64_u64(capacity << SCHED_CAPACITY_SHIFT, + capacity_scale); topology_set_cpu_scale(cpu, capacity); pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n", cpu, topology_get_cpu_scale(cpu)); @@ -127,6 +133,7 @@ void topology_normalize_cpu_scale(void) bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) { + struct clk *cpu_clk; static bool cap_parsing_failed; int ret; u32 cpu_capacity; @@ -146,10 +153,22 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) return false; } } - capacity_scale = max(cpu_capacity, capacity_scale); raw_capacity[cpu] = cpu_capacity; pr_debug("cpu_capacity: %pOF cpu_capacity=%u (raw)\n", cpu_node, raw_capacity[cpu]); + + /* + * Update freq_factor for calculating early boot cpu capacities. + * For non-clk CPU DVFS mechanism, there's no way to get the + * frequency value now, assuming they are running at the same + * frequency (by keeping the initial freq_factor value). + */ + cpu_clk = of_clk_get(cpu_node, 0); + if (!PTR_ERR_OR_ZERO(cpu_clk)) + per_cpu(freq_factor, cpu) = + clk_get_rate(cpu_clk) / 1000; + + clk_put(cpu_clk); } else { if (raw_capacity) { pr_err("cpu_capacity: missing %pOF raw capacity\n", @@ -188,11 +207,8 @@ init_cpu_capacity_callback(struct notifier_block *nb, cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus); - for_each_cpu(cpu, policy->related_cpus) { - raw_capacity[cpu] = topology_get_cpu_scale(cpu) * - policy->cpuinfo.max_freq / 1000UL; - capacity_scale = max(raw_capacity[cpu], capacity_scale); - } + for_each_cpu(cpu, policy->related_cpus) + per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq / 1000; if (cpumask_empty(cpus_to_visit)) { topology_normalize_cpu_scale(); -- cgit v1.2.3 From 4a33691c4cea9eb0a7c66e87248be4637e14b180 Mon Sep 17 00:00:00 2001 From: Zeng Tao Date: Wed, 4 Mar 2020 11:54:52 +0800 Subject: cpu-topology: Fix the potential data corruption Currently there are only 10 bytes to store the cpu-topology 'name' information. Only 10 bytes copied into cluster/thread/core names. If the cluster ID exceeds 2-digit number, it will result in the data corruption, and ending up in a dead loop in the parsing routines. The same applies to the thread names with more that 3-digit number. This issue was found using the boundary tests under virtualised environment like QEMU. Let us increase the buffer to fix such potential issues. Reviewed-by: Sudeep Holla Signed-off-by: Zeng Tao Link: https://lore.kernel.org/r/1583294092-5929-1-git-send-email-prime.zeng@hisilicon.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/arch_topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index b56c33e5b6a8..4cb1616d3871 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -297,7 +297,7 @@ static int __init get_cpu_for_node(struct device_node *node) static int __init parse_core(struct device_node *core, int package_id, int core_id) { - char name[10]; + char name[20]; bool leaf = true; int i = 0; int cpu; @@ -343,7 +343,7 @@ static int __init parse_core(struct device_node *core, int package_id, static int __init parse_cluster(struct device_node *cluster, int depth) { - char name[10]; + char name[20]; bool leaf = true; bool has_cores = false; struct device_node *c; -- cgit v1.2.3 From 4dfff3d55440a9f8726a0f7d62a9c33594b58b10 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Tue, 17 Mar 2020 14:33:08 +0800 Subject: arch_topology: Fix putting invalid cpu clk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a sanity check before putting the cpu clk. Fixes: b8fe128dad8f (“arch_topology: Adjust initial CPU capacities with current freq") Signed-off-by: Jeffy Chen Link: https://lore.kernel.org/r/20200317063308.23209-1-jeffy.chen@rock-chips.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/arch_topology.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 4cb1616d3871..e5d691cf824c 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -164,11 +164,11 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) * frequency (by keeping the initial freq_factor value). */ cpu_clk = of_clk_get(cpu_node, 0); - if (!PTR_ERR_OR_ZERO(cpu_clk)) + if (!PTR_ERR_OR_ZERO(cpu_clk)) { per_cpu(freq_factor, cpu) = clk_get_rate(cpu_clk) / 1000; - - clk_put(cpu_clk); + clk_put(cpu_clk); + } } else { if (raw_capacity) { pr_err("cpu_capacity: missing %pOF raw capacity\n", -- cgit v1.2.3 From bcfbd3523f3c6eea51a74d217a8ebc5463bcb7f4 Mon Sep 17 00:00:00 2001 From: Junyong Sun Date: Tue, 3 Mar 2020 10:36:08 +0800 Subject: firmware: fix a double abort case with fw_load_sysfs_fallback fw_sysfs_wait_timeout may return err with -ENOENT at fw_load_sysfs_fallback and firmware is already in abort status, no need to abort again, so skip it. This issue is caused by concurrent situation like below: when thread 1# wait firmware loading, thread 2# may write -1 to abort loading and wakeup thread 1# before it timeout. so wait_for_completion_killable_timeout of thread 1# would return remaining time which is != 0 with fw_st->status FW_STATUS_ABORTED.And the results would be converted into err -ENOENT in __fw_state_wait_common and transfered to fw_load_sysfs_fallback in thread 1#. The -ENOENT means firmware status is already at ABORTED, so fw_load_sysfs_fallback no need to get mutex to abort again. ----------------------------- thread 1#,wait for loading fw_load_sysfs_fallback ->fw_sysfs_wait_timeout ->__fw_state_wait_common ->wait_for_completion_killable_timeout in __fw_state_wait_common, ... 93 ret = wait_for_completion_killable_timeout(&fw_st->completion, timeout); 94 if (ret != 0 && fw_st->status == FW_STATUS_ABORTED) 95 return -ENOENT; 96 if (!ret) 97 return -ETIMEDOUT; 98 99 return ret < 0 ? ret : 0; ----------------------------- thread 2#, write -1 to abort loading firmware_loading_store ->fw_load_abort ->__fw_load_abort ->fw_state_aborted ->__fw_state_set ->complete_all in __fw_state_set, ... 111 if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED) 112 complete_all(&fw_st->completion); ------------------------------------------- BTW,the double abort issue would not cause kernel panic or create an issue, but slow down it sometimes.The change is just a minor optimization. Signed-off-by: Junyong Sun Acked-by: Luis Chamberlain Link: https://lore.kernel.org/r/1583202968-28792-1-git-send-email-sunjunyong@xiaomi.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_loader/fallback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c index 8704e1bae175..1e9c96e3ed63 100644 --- a/drivers/base/firmware_loader/fallback.c +++ b/drivers/base/firmware_loader/fallback.c @@ -525,7 +525,7 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, } retval = fw_sysfs_wait_timeout(fw_priv, timeout); - if (retval < 0) { + if (retval < 0 && retval != -ENOENT) { mutex_lock(&fw_lock); fw_load_abort(fw_sysfs); mutex_unlock(&fw_lock); -- cgit v1.2.3 From 14422f14da818a3f12344dceee47b4206870a24d Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Thu, 27 Feb 2020 11:45:47 +0100 Subject: component: allow missing unbind callback The component framework reuses the devres managed functions. There is no need to specify an unbind() callback if the driver only wants to release the devres managed resources. The bind/unbind is like the probe/remove pair. The bind/probe is necessary and the unbind/remove is optional. Signed-off-by: Marco Felsch Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20200227104547.30085-1-m.felsch@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/base/component.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/component.c b/drivers/base/component.c index c7879f5ae2fb..e97704104784 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -528,7 +528,8 @@ static void component_unbind(struct component *component, { WARN_ON(!component->bound); - component->ops->unbind(component->dev, master->dev, data); + if (component->ops && component->ops->unbind) + component->ops->unbind(component->dev, master->dev, data); component->bound = false; /* Release all resources claimed in the binding of this component */ -- cgit v1.2.3 From 8ba88804bb3b877c841bc1864a8605111580cd0b Mon Sep 17 00:00:00 2001 From: Madhuparna Bhowmik Date: Fri, 28 Feb 2020 23:17:45 +0530 Subject: drivers: base: power: wakeup.c: Use built-in RCU list checking Pass cond argument to list_for_each_entry_rcu() to fix the following false positive lockdep warning and other uses of list_for_each_entry_rcu() in wakeup.c. [ 331.934648] ============================= [ 331.934650] WARNING: suspicious RCU usage [ 331.934653] 5.6.0-rc1+ #5 Not tainted [ 331.934655] ----------------------------- [ 331.934657] drivers/base/power/wakeup.c:408 RCU-list traversed in non-reader section!! [ 333.025156] ============================= [ 333.025161] WARNING: suspicious RCU usage [ 333.025168] 5.6.0-rc1+ #5 Not tainted [ 333.025173] ----------------------------- [ 333.025180] drivers/base/power/wakeup.c:424 RCU-list traversed in non-reader section!! Cc: "Rafael J. Wysocki" Signed-off-by: Madhuparna Bhowmik Link: https://lore.kernel.org/r/20200228174745.9308-1-madhuparnabhowmik10@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/wakeup.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 27f3e60608e5..d9fefc65ac34 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -405,7 +405,8 @@ void device_wakeup_arm_wake_irqs(void) int srcuidx; srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) + list_for_each_entry_rcu(ws, &wakeup_sources, entry, + srcu_read_lock_held(&wakeup_srcu)) dev_pm_arm_wake_irq(ws->wakeirq); srcu_read_unlock(&wakeup_srcu, srcuidx); } @@ -421,7 +422,8 @@ void device_wakeup_disarm_wake_irqs(void) int srcuidx; srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) + list_for_each_entry_rcu(ws, &wakeup_sources, entry, + srcu_read_lock_held(&wakeup_srcu)) dev_pm_disarm_wake_irq(ws->wakeirq); srcu_read_unlock(&wakeup_srcu, srcuidx); } @@ -874,7 +876,8 @@ void pm_print_active_wakeup_sources(void) struct wakeup_source *last_activity_ws = NULL; srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) { + list_for_each_entry_rcu(ws, &wakeup_sources, entry, + srcu_read_lock_held(&wakeup_srcu)) { if (ws->active) { pm_pr_dbg("active wakeup source: %s\n", ws->name); active = 1; @@ -1025,7 +1028,8 @@ void pm_wakep_autosleep_enabled(bool set) int srcuidx; srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) { + list_for_each_entry_rcu(ws, &wakeup_sources, entry, + srcu_read_lock_held(&wakeup_srcu)) { spin_lock_irq(&ws->lock); if (ws->autosleep_enabled != set) { ws->autosleep_enabled = set; @@ -1104,7 +1108,8 @@ static void *wakeup_sources_stats_seq_start(struct seq_file *m, } *srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) { + list_for_each_entry_rcu(ws, &wakeup_sources, entry, + srcu_read_lock_held(&wakeup_srcu)) { if (n-- <= 0) return ws; } -- cgit v1.2.3 From 99917e37b9e78b96af304ddeb4f9b82a5948bbd9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 19 Mar 2020 10:20:27 +0100 Subject: Revert "drivers: base: power: wakeup.c: Use built-in RCU list checking" This reverts commit 8ba88804bb3b877c841bc1864a8605111580cd0b as a better version is already in Rafael's tree, sorry about that. Reported-by: "Rafael J. Wysocki" Cc: Madhuparna Bhowmik Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/wakeup.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index d9fefc65ac34..27f3e60608e5 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -405,8 +405,7 @@ void device_wakeup_arm_wake_irqs(void) int srcuidx; srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry, - srcu_read_lock_held(&wakeup_srcu)) + list_for_each_entry_rcu(ws, &wakeup_sources, entry) dev_pm_arm_wake_irq(ws->wakeirq); srcu_read_unlock(&wakeup_srcu, srcuidx); } @@ -422,8 +421,7 @@ void device_wakeup_disarm_wake_irqs(void) int srcuidx; srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry, - srcu_read_lock_held(&wakeup_srcu)) + list_for_each_entry_rcu(ws, &wakeup_sources, entry) dev_pm_disarm_wake_irq(ws->wakeirq); srcu_read_unlock(&wakeup_srcu, srcuidx); } @@ -876,8 +874,7 @@ void pm_print_active_wakeup_sources(void) struct wakeup_source *last_activity_ws = NULL; srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry, - srcu_read_lock_held(&wakeup_srcu)) { + list_for_each_entry_rcu(ws, &wakeup_sources, entry) { if (ws->active) { pm_pr_dbg("active wakeup source: %s\n", ws->name); active = 1; @@ -1028,8 +1025,7 @@ void pm_wakep_autosleep_enabled(bool set) int srcuidx; srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry, - srcu_read_lock_held(&wakeup_srcu)) { + list_for_each_entry_rcu(ws, &wakeup_sources, entry) { spin_lock_irq(&ws->lock); if (ws->autosleep_enabled != set) { ws->autosleep_enabled = set; @@ -1108,8 +1104,7 @@ static void *wakeup_sources_stats_seq_start(struct seq_file *m, } *srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry, - srcu_read_lock_held(&wakeup_srcu)) { + list_for_each_entry_rcu(ws, &wakeup_sources, entry) { if (n-- <= 0) return ws; } -- cgit v1.2.3 From e4c2c0ff00ecaf8e245455a199b86ce22143becf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 15 Jan 2020 17:35:48 +0100 Subject: firmware: Add new platform fallback mechanism and firmware_request_platform() In some cases the platform's main firmware (e.g. the UEFI fw) may contain an embedded copy of device firmware which needs to be (re)loaded into the peripheral. Normally such firmware would be part of linux-firmware, but in some cases this is not feasible, for 2 reasons: 1) The firmware is customized for a specific use-case of the chipset / use with a specific hardware model, so we cannot have a single firmware file for the chipset. E.g. touchscreen controller firmwares are compiled specifically for the hardware model they are used with, as they are calibrated for a specific model digitizer. 2) Despite repeated attempts we have failed to get permission to redistribute the firmware. This is especially a problem with customized firmwares, these get created by the chip vendor for a specific ODM and the copyright may partially belong with the ODM, so the chip vendor cannot give a blanket permission to distribute these. This commit adds a new platform fallback mechanism to the firmware loader which will try to lookup a device fw copy embedded in the platform's main firmware if direct filesystem lookup fails. Drivers which need such embedded fw copies can enable this fallback mechanism by using the new firmware_request_platform() function. Note that for now this is only supported on EFI platforms and even on these platforms firmware_fallback_platform() only works if CONFIG_EFI_EMBEDDED_FIRMWARE is enabled (this gets selected by drivers which need this), in all other cases firmware_fallback_platform() simply always returns -ENOENT. Reported-by: Dave Olsthoorn Suggested-by: Peter Jones Acked-by: Luis Chamberlain Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20200115163554.101315-5-hdegoede@redhat.com Signed-off-by: Greg Kroah-Hartman --- .../driver-api/firmware/fallback-mechanisms.rst | 103 +++++++++++++++++++++ Documentation/driver-api/firmware/lookup-order.rst | 2 + .../driver-api/firmware/request_firmware.rst | 5 + drivers/base/firmware_loader/Makefile | 1 + drivers/base/firmware_loader/fallback.h | 10 ++ drivers/base/firmware_loader/fallback_platform.c | 36 +++++++ drivers/base/firmware_loader/firmware.h | 4 + drivers/base/firmware_loader/main.c | 27 ++++++ include/linux/firmware.h | 9 ++ include/linux/fs.h | 1 + 10 files changed, 198 insertions(+) create mode 100644 drivers/base/firmware_loader/fallback_platform.c (limited to 'drivers/base') diff --git a/Documentation/driver-api/firmware/fallback-mechanisms.rst b/Documentation/driver-api/firmware/fallback-mechanisms.rst index 8b041d0ab426..036383dad6d6 100644 --- a/Documentation/driver-api/firmware/fallback-mechanisms.rst +++ b/Documentation/driver-api/firmware/fallback-mechanisms.rst @@ -202,3 +202,106 @@ the following file: If you echo 0 into it means MAX_JIFFY_OFFSET will be used. The data type for the timeout is an int. + +EFI embedded firmware fallback mechanism +======================================== + +On some devices the system's EFI code / ROM may contain an embedded copy +of firmware for some of the system's integrated peripheral devices and +the peripheral's Linux device-driver needs to access this firmware. + +Device drivers which need such firmware can use the +firmware_request_platform() function for this, note that this is a +separate fallback mechanism from the other fallback mechanisms and +this does not use the sysfs interface. + +A device driver which needs this can describe the firmware it needs +using an efi_embedded_fw_desc struct: + +.. kernel-doc:: include/linux/efi_embedded_fw.h + :functions: efi_embedded_fw_desc + +The EFI embedded-fw code works by scanning all EFI_BOOT_SERVICES_CODE memory +segments for an eight byte sequence matching prefix; if the prefix is found it +then does a sha256 over length bytes and if that matches makes a copy of length +bytes and adds that to its list with found firmwares. + +To avoid doing this somewhat expensive scan on all systems, dmi matching is +used. Drivers are expected to export a dmi_system_id array, with each entries' +driver_data pointing to an efi_embedded_fw_desc. + +To register this array with the efi-embedded-fw code, a driver needs to: + +1. Always be builtin to the kernel or store the dmi_system_id array in a + separate object file which always gets builtin. + +2. Add an extern declaration for the dmi_system_id array to + include/linux/efi_embedded_fw.h. + +3. Add the dmi_system_id array to the embedded_fw_table in + drivers/firmware/efi/embedded-firmware.c wrapped in a #ifdef testing that + the driver is being builtin. + +4. Add "select EFI_EMBEDDED_FIRMWARE if EFI_STUB" to its Kconfig entry. + +The firmware_request_platform() function will always first try to load firmware +with the specified name directly from the disk, so the EFI embedded-fw can +always be overridden by placing a file under /lib/firmware. + +Note that: + +1. The code scanning for EFI embedded-firmware runs near the end + of start_kernel(), just before calling rest_init(). For normal drivers and + subsystems using subsys_initcall() to register themselves this does not + matter. This means that code running earlier cannot use EFI + embedded-firmware. + +2. At the moment the EFI embedded-fw code assumes that firmwares always start at + an offset which is a multiple of 8 bytes, if this is not true for your case + send in a patch to fix this. + +3. At the moment the EFI embedded-fw code only works on x86 because other archs + free EFI_BOOT_SERVICES_CODE before the EFI embedded-fw code gets a chance to + scan it. + +4. The current brute-force scanning of EFI_BOOT_SERVICES_CODE is an ad-hoc + brute-force solution. There has been discussion to use the UEFI Platform + Initialization (PI) spec's Firmware Volume protocol. This has been rejected + because the FV Protocol relies on *internal* interfaces of the PI spec, and: + 1. The PI spec does not define peripheral firmware at all + 2. The internal interfaces of the PI spec do not guarantee any backward + compatibility. Any implementation details in FV may be subject to change, + and may vary system to system. Supporting the FV Protocol would be + difficult as it is purposely ambiguous. + +Example how to check for and extract embedded firmware +------------------------------------------------------ + +To check for, for example Silead touchscreen controller embedded firmware, +do the following: + +1. Boot the system with efi=debug on the kernel commandline + +2. cp /sys/kernel/debug/efi/boot_services_code? to your home dir + +3. Open the boot_services_code? files in a hex-editor, search for the + magic prefix for Silead firmware: F0 00 00 00 02 00 00 00, this gives you + the beginning address of the firmware inside the boot_services_code? file. + +4. The firmware has a specific pattern, it starts with a 8 byte page-address, + typically F0 00 00 00 02 00 00 00 for the first page followed by 32-bit + word-address + 32-bit value pairs. With the word-address incrementing 4 + bytes (1 word) for each pair until a page is complete. A complete page is + followed by a new page-address, followed by more word + value pairs. This + leads to a very distinct pattern. Scroll down until this pattern stops, + this gives you the end of the firmware inside the boot_services_code? file. + +5. "dd if=boot_services_code? of=firmware bs=1 skip= count=" + will extract the firmware for you. Inspect the firmware file in a + hexeditor to make sure you got the dd parameters correct. + +6. Copy it to /lib/firmware under the expected name to test it. + +7. If the extracted firmware works, you can use the found info to fill an + efi_embedded_fw_desc struct to describe it, run "sha256sum firmware" + to get the sha256sum to put in the sha256 field. diff --git a/Documentation/driver-api/firmware/lookup-order.rst b/Documentation/driver-api/firmware/lookup-order.rst index 88c81739683c..6064672a782e 100644 --- a/Documentation/driver-api/firmware/lookup-order.rst +++ b/Documentation/driver-api/firmware/lookup-order.rst @@ -12,6 +12,8 @@ a driver issues a firmware API call. return it immediately * The ''Direct filesystem lookup'' is performed next, if found we return it immediately +* The ''Platform firmware fallback'' is performed next, but only when + firmware_request_platform() is used, if found we return it immediately * If no firmware has been found and the fallback mechanism was enabled the sysfs interface is created. After this either a kobject uevent is issued or the custom firmware loading is relied upon for firmware diff --git a/Documentation/driver-api/firmware/request_firmware.rst b/Documentation/driver-api/firmware/request_firmware.rst index f62bdcbfed5b..cd076462d235 100644 --- a/Documentation/driver-api/firmware/request_firmware.rst +++ b/Documentation/driver-api/firmware/request_firmware.rst @@ -25,6 +25,11 @@ firmware_request_nowarn .. kernel-doc:: drivers/base/firmware_loader/main.c :functions: firmware_request_nowarn +firmware_request_platform +------------------------- +.. kernel-doc:: drivers/base/firmware_loader/main.c + :functions: firmware_request_platform + request_firmware_direct ----------------------- .. kernel-doc:: drivers/base/firmware_loader/main.c diff --git a/drivers/base/firmware_loader/Makefile b/drivers/base/firmware_loader/Makefile index 0b2dfa6259c9..e87843408fe6 100644 --- a/drivers/base/firmware_loader/Makefile +++ b/drivers/base/firmware_loader/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_FW_LOADER_USER_HELPER) += fallback_table.o obj-$(CONFIG_FW_LOADER) += firmware_class.o firmware_class-objs := main.o firmware_class-$(CONFIG_FW_LOADER_USER_HELPER) += fallback.o +firmware_class-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += fallback_platform.o obj-y += builtin/ diff --git a/drivers/base/firmware_loader/fallback.h b/drivers/base/firmware_loader/fallback.h index 21063503e4ea..06f4577733a8 100644 --- a/drivers/base/firmware_loader/fallback.h +++ b/drivers/base/firmware_loader/fallback.h @@ -66,4 +66,14 @@ static inline void unregister_sysfs_loader(void) } #endif /* CONFIG_FW_LOADER_USER_HELPER */ +#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE +int firmware_fallback_platform(struct fw_priv *fw_priv, enum fw_opt opt_flags); +#else +static inline int firmware_fallback_platform(struct fw_priv *fw_priv, + enum fw_opt opt_flags) +{ + return -ENOENT; +} +#endif + #endif /* __FIRMWARE_FALLBACK_H */ diff --git a/drivers/base/firmware_loader/fallback_platform.c b/drivers/base/firmware_loader/fallback_platform.c new file mode 100644 index 000000000000..c88c745590fe --- /dev/null +++ b/drivers/base/firmware_loader/fallback_platform.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +#include "fallback.h" +#include "firmware.h" + +int firmware_fallback_platform(struct fw_priv *fw_priv, enum fw_opt opt_flags) +{ + const u8 *data; + size_t size; + int rc; + + if (!(opt_flags & FW_OPT_FALLBACK_PLATFORM)) + return -ENOENT; + + rc = security_kernel_load_data(LOADING_FIRMWARE_EFI_EMBEDDED); + if (rc) + return rc; + + rc = efi_get_embedded_fw(fw_priv->fw_name, &data, &size); + if (rc) + return rc; /* rc == -ENOENT when the fw was not found */ + + fw_priv->data = vmalloc(size); + if (!fw_priv->data) + return -ENOMEM; + + memcpy(fw_priv->data, data, size); + fw_priv->size = size; + fw_state_done(fw_priv); + return 0; +} diff --git a/drivers/base/firmware_loader/firmware.h b/drivers/base/firmware_loader/firmware.h index 8656e5239a80..25836a6afc9f 100644 --- a/drivers/base/firmware_loader/firmware.h +++ b/drivers/base/firmware_loader/firmware.h @@ -29,6 +29,9 @@ * firmware caching mechanism. * @FW_OPT_NOFALLBACK_SYSFS: Disable the sysfs fallback mechanism. Takes * precedence over &FW_OPT_UEVENT and &FW_OPT_USERHELPER. + * @FW_OPT_FALLBACK_PLATFORM: Enable fallback to device fw copy embedded in + * the platform's main firmware. If both this fallback and the sysfs + * fallback are enabled, then this fallback will be tried first. */ enum fw_opt { FW_OPT_UEVENT = BIT(0), @@ -37,6 +40,7 @@ enum fw_opt { FW_OPT_NO_WARN = BIT(3), FW_OPT_NOCACHE = BIT(4), FW_OPT_NOFALLBACK_SYSFS = BIT(5), + FW_OPT_FALLBACK_PLATFORM = BIT(6), }; enum fw_status { diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 59d1dc322080..76f79913916d 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -778,6 +778,9 @@ _request_firmware(const struct firmware **firmware_p, const char *name, fw_decompress_xz); #endif + if (ret == -ENOENT) + ret = firmware_fallback_platform(fw->priv, opt_flags); + if (ret) { if (!(opt_flags & FW_OPT_NO_WARN)) dev_warn(device, @@ -885,6 +888,30 @@ int request_firmware_direct(const struct firmware **firmware_p, } EXPORT_SYMBOL_GPL(request_firmware_direct); +/** + * firmware_request_platform() - request firmware with platform-fw fallback + * @firmware: pointer to firmware image + * @name: name of firmware file + * @device: device for which firmware is being loaded + * + * This function is similar in behaviour to request_firmware, except that if + * direct filesystem lookup fails, it will fallback to looking for a copy of the + * requested firmware embedded in the platform's main (e.g. UEFI) firmware. + **/ +int firmware_request_platform(const struct firmware **firmware, + const char *name, struct device *device) +{ + int ret; + + /* Need to pin this module until return */ + __module_get(THIS_MODULE); + ret = _request_firmware(firmware, name, device, NULL, 0, + FW_OPT_UEVENT | FW_OPT_FALLBACK_PLATFORM); + module_put(THIS_MODULE); + return ret; +} +EXPORT_SYMBOL_GPL(firmware_request_platform); + /** * firmware_request_cache() - cache firmware for suspend so resume can use it * @name: name of firmware file diff --git a/include/linux/firmware.h b/include/linux/firmware.h index 2dd566c91d44..4bbd0afd91b7 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -44,6 +44,8 @@ int request_firmware(const struct firmware **fw, const char *name, struct device *device); int firmware_request_nowarn(const struct firmware **fw, const char *name, struct device *device); +int firmware_request_platform(const struct firmware **fw, const char *name, + struct device *device); int request_firmware_nowait( struct module *module, bool uevent, const char *name, struct device *device, gfp_t gfp, void *context, @@ -69,6 +71,13 @@ static inline int firmware_request_nowarn(const struct firmware **fw, return -EINVAL; } +static inline int firmware_request_platform(const struct firmware **fw, + const char *name, + struct device *device) +{ + return -EINVAL; +} + static inline int request_firmware_nowait( struct module *module, bool uevent, const char *name, struct device *device, gfp_t gfp, void *context, diff --git a/include/linux/fs.h b/include/linux/fs.h index f814ccd8d929..8e08f7f0cd5f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2982,6 +2982,7 @@ extern int do_pipe_flags(int *, int); id(UNKNOWN, unknown) \ id(FIRMWARE, firmware) \ id(FIRMWARE_PREALLOC_BUFFER, firmware) \ + id(FIRMWARE_EFI_EMBEDDED, firmware) \ id(MODULE, kernel-module) \ id(KEXEC_IMAGE, kexec-image) \ id(KEXEC_INITRAMFS, kexec-initramfs) \ -- cgit v1.2.3 From 4dbe191c046e71d6ea1ba85365ecb33961b07c4f Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Fri, 20 Mar 2020 21:54:48 -0700 Subject: driver core: Add device links from fwnode only for the primary device Sometimes, more than one (generally two) device can point to the same fwnode. However, only one device is set as the fwnode's device (fwnode->dev) and can be looked up from the fwnode. Typically, only one of these devices actually have a driver and actually probe. If we create device links for all these devices, then the suppliers' of these devices (with the same fwnode) will never get a sync_state() call because one of their consumer devices will never probe (because they don't have a driver). So, create device links only for the device that is considered as the fwnode's device. One such example of this is the PCI bridge platform_device and the corresponding pci_bus device. Both these devices will have the same fwnode. It's the platform_device that is registered first and is set as the fwnode's device. Also the platform_device is the one that actually probes. Without this patch none of the suppliers of a PCI bridge platform_device would get a sync_state() callback. Cc: Bjorn Helgaas Cc: linux-pci@vger.kernel.org Reviewed-by: Rafael J. Wysocki Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20200321045448.15192-1-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index fc6a60998cd6..5e3cc1651c78 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2404,6 +2404,7 @@ int device_add(struct device *dev) struct class_interface *class_intf; int error = -EINVAL, fw_ret; struct kobject *glue_dir = NULL; + bool is_fwnode_dev = false; dev = get_device(dev); if (!dev) @@ -2501,8 +2502,10 @@ int device_add(struct device *dev) kobject_uevent(&dev->kobj, KOBJ_ADD); - if (dev->fwnode && !dev->fwnode->dev) + if (dev->fwnode && !dev->fwnode->dev) { dev->fwnode->dev = dev; + is_fwnode_dev = true; + } /* * Check if any of the other devices (consumers) have been waiting for @@ -2518,7 +2521,8 @@ int device_add(struct device *dev) */ device_link_add_missing_supplier_links(); - if (fw_devlink_flags && fwnode_has_op(dev->fwnode, add_links)) { + if (fw_devlink_flags && is_fwnode_dev && + fwnode_has_op(dev->fwnode, add_links)) { fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev); if (fw_ret == -ENODEV) device_link_wait_for_mandatory_supplier(dev); -- cgit v1.2.3 From 927f82875c272e8c1159cb2c00bda473402c7c28 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 24 Mar 2020 14:20:22 +0200 Subject: driver core: Read atomic counter once in driver_probe_done() Between printing the debug message and actual check atomic counter can be altered. For better debugging experience read atomic counter value only once. Signed-off-by: Andy Shevchenko Tested-by: Ferry Toth Link: https://lore.kernel.org/r/20200324122023.9649-2-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 76888a7459d8..3f5b8bdd94f0 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -644,9 +644,10 @@ static int really_probe_debug(struct device *dev, struct device_driver *drv) */ int driver_probe_done(void) { - pr_debug("%s: probe_count = %d\n", __func__, - atomic_read(&probe_count)); - if (atomic_read(&probe_count)) + int local_probe_count = atomic_read(&probe_count); + + pr_debug("%s: probe_count = %d\n", __func__, local_probe_count); + if (local_probe_count) return -EBUSY; return 0; } -- cgit v1.2.3 From a3a87d66d3f64c74acbc25799d38effb63695ea0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 24 Mar 2020 14:20:23 +0200 Subject: driver core: Replace open-coded list_last_entry() There is a place in the code where open-coded version of list entry accessors list_last_entry() is used. Replace that with the standard macro. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200324122023.9649-3-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 3f5b8bdd94f0..06ec0e851fa1 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -1199,7 +1199,7 @@ void driver_detach(struct device_driver *drv) spin_unlock(&drv->p->klist_devices.k_lock); break; } - dev_prv = list_entry(drv->p->klist_devices.k_list.prev, + dev_prv = list_last_entry(&drv->p->klist_devices.k_list, struct device_private, knode_driver.n_node); dev = dev_prv->device; -- cgit v1.2.3 From c442a0d18744d4a5857d513f171d68ed6a54df5b Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Sat, 21 Mar 2020 14:03:05 -0700 Subject: driver core: Set fw_devlink to "permissive" behavior by default Set fw_devlink to "permissive" behavior by default so that device links are automatically created (with DL_FLAG_SYNC_STATE_ONLY) by scanning the firmware. This ensures suppliers get their sync_state() calls only after all their consumers have probed successfully. Without this, suppliers will get their sync_state() calls at late_initcall_sync() even if their consuer Ideally, we'd want to set fw_devlink to "on" or "rpm" by default. But that needs more testing as it's known to break some corner case drivers/platforms. Cc: Rob Herring Cc: Frank Rowand Cc: devicetree@vger.kernel.org Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20200321210305.28937-1-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 5e3cc1651c78..9fabf9749a06 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2345,7 +2345,7 @@ static int device_private_init(struct device *dev) return 0; } -static u32 fw_devlink_flags; +static u32 fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY; static int __init fw_devlink_setup(char *arg) { if (!arg) -- cgit v1.2.3 From 18555cb6db2373b9a5ec1f7572773fd58c77f9ba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 27 Mar 2020 16:17:30 +0100 Subject: Revert "driver core: Set fw_devlink to "permissive" behavior by default" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c442a0d18744d4a5857d513f171d68ed6a54df5b as it breaks some of the Raspberry Pi devices. Marek writes: This patch has just landed in linux-next 20200326. Sadly it breaks booting of the Raspberry Pi3b and Pi4 boards, either in 32bit or 64bit mode. There is no warning nor panic message, just a silent freeze. The last message shown on the earlycon is: [    0.893217] Serial: 8250/16550 driver, 1 ports, IRQ sharing enabled so revert it for now and let's try again and add it to linux-next after 5.7-rc1 is out so that we can try to get more debugging/testing happening. Reported-by: Marek Szyprowski Cc: Rob Herring Cc: Frank Rowand Cc: Saravana Kannan Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 9fabf9749a06..5e3cc1651c78 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2345,7 +2345,7 @@ static int device_private_init(struct device *dev) return 0; } -static u32 fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY; +static u32 fw_devlink_flags; static int __init fw_devlink_setup(char *arg) { if (!arg) -- cgit v1.2.3