mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 05:06:29 +00:00
firmware: coreboot: Register bus in module init
The coreboot_table driver registers a coreboot bus while probing a
"coreboot_table" device representing the coreboot table memory region.
Probing this device (i.e., registering the bus) is a dependency for the
module_init() functions of any driver for this bus (e.g.,
memconsole-coreboot.c / memconsole_driver_init()).
With synchronous probe, this dependency works OK, as the link order in
the Makefile ensures coreboot_table_driver_init() (and thus,
coreboot_table_probe()) completes before a coreboot device driver tries
to add itself to the bus.
With asynchronous probe, however, coreboot_table_probe() may race with
memconsole_driver_init(), and so we're liable to hit one of these two:
1. coreboot_driver_register() eventually hits "[...] the bus was not
initialized.", and the memconsole driver fails to register; or
2. coreboot_driver_register() gets past #1, but still races with
bus_register() and hits some other undefined/crashing behavior (e.g.,
in driver_find() [1])
We can resolve this by registering the bus in our initcall, and only
deferring "device" work (scanning the coreboot memory region and
creating sub-devices) to probe().
[1] Example failure, using 'driver_async_probe=*' kernel command line:
[ 0.114217] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010
...
[ 0.114307] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.1.0-rc1 #63
[ 0.114316] Hardware name: Google Scarlet (DT)
...
[ 0.114488] Call trace:
[ 0.114494] _raw_spin_lock+0x34/0x60
[ 0.114502] kset_find_obj+0x28/0x84
[ 0.114511] driver_find+0x30/0x50
[ 0.114520] driver_register+0x64/0x10c
[ 0.114528] coreboot_driver_register+0x30/0x3c
[ 0.114540] memconsole_driver_init+0x24/0x30
[ 0.114550] do_one_initcall+0x154/0x2e0
[ 0.114560] do_initcall_level+0x134/0x160
[ 0.114571] do_initcalls+0x60/0xa0
[ 0.114579] do_basic_setup+0x28/0x34
[ 0.114588] kernel_init_freeable+0xf8/0x150
[ 0.114596] kernel_init+0x2c/0x12c
[ 0.114607] ret_from_fork+0x10/0x20
[ 0.114624] Code: 5280002b 1100054a b900092a f9800011 (885ffc01)
[ 0.114631] ---[ end trace 0000000000000000 ]---
Fixes: b81e3140e4
("firmware: coreboot: Make bus registration symmetric")
Cc: <stable@vger.kernel.org>
Signed-off-by: Brian Norris <briannorris@chromium.org>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20221019180934.1.If29e167d8a4771b0bf4a39c89c6946ed764817b9@changeid
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ee424f7d39
commit
65946690ed
@ -149,12 +149,8 @@ static int coreboot_table_probe(struct platform_device *pdev)
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = bus_register(&coreboot_bus_type);
|
||||
if (!ret) {
|
||||
ret = coreboot_table_populate(dev, ptr);
|
||||
if (ret)
|
||||
bus_unregister(&coreboot_bus_type);
|
||||
}
|
||||
ret = coreboot_table_populate(dev, ptr);
|
||||
|
||||
memunmap(ptr);
|
||||
|
||||
return ret;
|
||||
@ -169,7 +165,6 @@ static int __cb_dev_unregister(struct device *dev, void *dummy)
|
||||
static int coreboot_table_remove(struct platform_device *pdev)
|
||||
{
|
||||
bus_for_each_dev(&coreboot_bus_type, NULL, NULL, __cb_dev_unregister);
|
||||
bus_unregister(&coreboot_bus_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -199,6 +194,32 @@ static struct platform_driver coreboot_table_driver = {
|
||||
.of_match_table = of_match_ptr(coreboot_of_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(coreboot_table_driver);
|
||||
|
||||
static int __init coreboot_table_driver_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bus_register(&coreboot_bus_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = platform_driver_register(&coreboot_table_driver);
|
||||
if (ret) {
|
||||
bus_unregister(&coreboot_bus_type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit coreboot_table_driver_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&coreboot_table_driver);
|
||||
bus_unregister(&coreboot_bus_type);
|
||||
}
|
||||
|
||||
module_init(coreboot_table_driver_init);
|
||||
module_exit(coreboot_table_driver_exit);
|
||||
|
||||
MODULE_AUTHOR("Google, Inc.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
Loading…
Reference in New Issue
Block a user