Skip to content

Commit ab3428c

Browse files
Russell King (Oracle)gregkh
authored andcommitted
nvmem: core: fix registration vs use race
The i.MX6 CPU frequency driver sometimes fails to register at boot time due to nvmem_cell_read_u32() sporadically returning -ENOENT. This happens because there is a window where __nvmem_device_get() in of_nvmem_cell_get() is able to return the nvmem device, but as cells have been setup, nvmem_find_cell_entry_by_node() returns NULL. The occurs because the nvmem core registration code violates one of the fundamental principles of kernel programming: do not publish data structures before their setup is complete. Fix this by making nvmem core code conform with this principle. Fixes: eace75c ("nvmem: Add a simple NVMEM framework for nvmem providers") Cc: [email protected] Signed-off-by: Russell King (Oracle) <[email protected]> Signed-off-by: Srinivas Kandagatla <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 560181d commit ab3428c

File tree

1 file changed

+8
-10
lines changed

1 file changed

+8
-10
lines changed

drivers/nvmem/core.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -832,22 +832,16 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
832832
nvmem->dev.groups = nvmem_dev_groups;
833833
#endif
834834

835-
dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
836-
837-
rval = device_add(&nvmem->dev);
838-
if (rval)
839-
goto err_put_device;
840-
841835
if (nvmem->nkeepout) {
842836
rval = nvmem_validate_keepouts(nvmem);
843837
if (rval)
844-
goto err_device_del;
838+
goto err_put_device;
845839
}
846840

847841
if (config->compat) {
848842
rval = nvmem_sysfs_setup_compat(nvmem, config);
849843
if (rval)
850-
goto err_device_del;
844+
goto err_put_device;
851845
}
852846

853847
if (config->cells) {
@@ -864,6 +858,12 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
864858
if (rval)
865859
goto err_remove_cells;
866860

861+
dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
862+
863+
rval = device_add(&nvmem->dev);
864+
if (rval)
865+
goto err_remove_cells;
866+
867867
blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
868868

869869
return nvmem;
@@ -873,8 +873,6 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
873873
err_teardown_compat:
874874
if (config->compat)
875875
nvmem_sysfs_remove_compat(nvmem, config);
876-
err_device_del:
877-
device_del(&nvmem->dev);
878876
err_put_device:
879877
put_device(&nvmem->dev);
880878

0 commit comments

Comments
 (0)