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: Geert Uytterhoeven <geert+renesas@glider.be> Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
This commit is contained in:
parent
12ca718846
commit
0b37a83a91
1 changed files with 9 additions and 13 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue