Messages in this thread | | | Date | Wed, 19 Oct 2022 18:20:08 -0700 | Subject | Re: [PATCH] firmware: coreboot: Register bus in module init | From | Guenter Roeck <> |
| |
On 10/19/22 18:10, Brian Norris wrote: > 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: b81e3140e412 ("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>
> --- > Currently, get_maintainers.pl tells me Greg should pick this up. But I > CC the chrome-platform list too, since it seems reasonable for Google > folks (probably ChromeOS folks are most active here?) to maintain > Google/Chrome drivers. > > Let me know if y'all would like this official, and I'll push out a > MAINTAINERS patch. >
I think that would be a good idea.
Guenter
> drivers/firmware/google/coreboot_table.c | 37 +++++++++++++++++++----- > 1 file changed, 29 insertions(+), 8 deletions(-) > > diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c > index c52bcaa9def6..9ca21feb9d45 100644 > --- a/drivers/firmware/google/coreboot_table.c > +++ b/drivers/firmware/google/coreboot_table.c > @@ -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");
| |