diff options
author | Nicolas Pitre <nicolas.pitre@linaro.org> | 2012-11-29 22:13:08 -0500 |
---|---|---|
committer | Jon Medhurst <tixy@linaro.org> | 2013-04-29 09:43:15 +0100 |
commit | f6863ac8241d0a31fb70faaa09fbb5e3394304ef (patch) | |
tree | c188a87183dc46668f53e26295684534a79e591c /drivers | |
parent | f7f504c31c18cf4ac1bf35cdb946553c31f3af20 (diff) |
misc: vexpress/spc: attempt to init the spc driver from vexpress_spc_check_loaded()
Even if it is initialized via early_INITCALL(), there are other pieces
of code that also have to be initialized with early_initcall() and
the relative call ordering may not always be satisfied.
So try to initialize the SPC code when vexpress_spc_check_loaded() is
called if that has not been done yet.
Signed-off-by: Nicolas Pitre <nico@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/vexpress/arm-spc.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/misc/vexpress/arm-spc.c b/drivers/misc/vexpress/arm-spc.c index 82ca8efcd17..0432e3d9506 100644 --- a/drivers/misc/vexpress/arm-spc.c +++ b/drivers/misc/vexpress/arm-spc.c @@ -538,14 +538,6 @@ int vexpress_spc_wfi_cpustat(int cluster) } EXPORT_SYMBOL_GPL(vexpress_spc_wfi_cpustat); -static bool vexpress_spc_loaded; - -bool vexpress_spc_check_loaded(void) -{ - return vexpress_spc_loaded; -} -EXPORT_SYMBOL_GPL(vexpress_spc_check_loaded); - irqreturn_t vexpress_spc_irq_handler(int irq, void *data) { struct vexpress_spc_drvdata *drv_data = data; @@ -624,10 +616,12 @@ static int vexpress_spc_populate_opps(uint32_t cluster) return ret; } -static int __init vexpress_spc_early_init(void) +static int vexpress_spc_init(void) { struct device_node *node = of_find_compatible_node(NULL, NULL, "arm,spc"); + if (!node) + return -ENODEV; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { @@ -635,9 +629,7 @@ static int __init vexpress_spc_early_init(void) return -ENOMEM; } - if (node) - info->baseaddr = of_iomap(node, 0); - + info->baseaddr = of_iomap(node, 0); if (WARN_ON(!info->baseaddr)) { kfree(info); return -EIO; @@ -684,11 +676,31 @@ static int __init vexpress_spc_early_init(void) outer_clean_range(virt_to_phys(info), virt_to_phys(info + 1)); pr_info("vexpress_spc loaded at %p\n", info->baseaddr); - vexpress_spc_loaded = true; - return 0; } +static int vexpress_spc_load_result = -EAGAIN; +static DEFINE_MUTEX(vexpress_spc_loading); + +bool vexpress_spc_check_loaded(void) +{ + if (vexpress_spc_load_result != -EAGAIN) + return (vexpress_spc_load_result == 0); + + mutex_lock(&vexpress_spc_loading); + if (vexpress_spc_load_result == -EAGAIN) + vexpress_spc_load_result = vexpress_spc_init(); + mutex_unlock(&vexpress_spc_loading); + return (vexpress_spc_load_result == 0); +} +EXPORT_SYMBOL_GPL(vexpress_spc_check_loaded); + +static int __init vexpress_spc_early_init(void) +{ + vexpress_spc_check_loaded(); + return vexpress_spc_load_result; +} + early_initcall(vexpress_spc_early_init); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Serial Power Controller (SPC) support"); |