Commit 0b37a83a authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Eduardo Valentin

thermal: rcar: Fix race condition between init and interrupt

As soon as the interrupt has been enabled by devm_request_irq(), the
interrupt routine may be called, depending on the current status of the
hardware.

However, at that point rcar_thermal_common hasn't been initialized
complely yet. E.g. rcar_thermal_common.base is still NULL, causing a
NULL pointer dereference:

    Unable to handle kernel NULL pointer dereference at virtual address 0000000c
    pgd = c0004000
    [0000000c] *pgd=00000000
    Internal error: Oops: 5 [#1] SMP ARM
    CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.19.0-rc7-ape6evm-04564-gb6e46cb7cbe82389 #30
    Hardware name: Generic R8A73A4 (Flattened Device Tree)
    task: ee8953c0 ti: ee896000 task.ti: ee896000
    PC is at rcar_thermal_irq+0x1c/0xf0
    LR is at _raw_spin_lock_irqsave+0x48/0x54

Postpone the call to devm_request_irq() until all initialization has
been done to fix this.
Signed-off-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Acked-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarEduardo Valentin <edubezval@gmail.com>
parent 12ca7188
...@@ -387,21 +387,9 @@ static int rcar_thermal_probe(struct platform_device *pdev) ...@@ -387,21 +387,9 @@ static int rcar_thermal_probe(struct platform_device *pdev)
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq) { if (irq) {
int ret;
/* /*
* platform has IRQ support. * platform has IRQ support.
* Then, driver uses common registers * Then, driver uses common registers
*/
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0,
dev_name(dev), common);
if (ret) {
dev_err(dev, "irq request failed\n ");
return ret;
}
/*
* rcar_has_irq_support() will be enabled * rcar_has_irq_support() will be enabled
*/ */
res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
...@@ -456,8 +444,16 @@ static int rcar_thermal_probe(struct platform_device *pdev) ...@@ -456,8 +444,16 @@ static int rcar_thermal_probe(struct platform_device *pdev)
} }
/* enable temperature comparation */ /* enable temperature comparation */
if (irq) if (irq) {
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0,
dev_name(dev), common);
if (ret) {
dev_err(dev, "irq request failed\n ");
goto error_unregister;
}
rcar_thermal_common_write(common, ENR, enr_bits); rcar_thermal_common_write(common, ENR, enr_bits);
}
platform_set_drvdata(pdev, common); platform_set_drvdata(pdev, common);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment