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>
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq) {
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq) {
/*
* platform has IRQ support.
* Then, driver uses common registers
/*
* platform has IRQ support.
* 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
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
* rcar_has_irq_support() will be enabled
*/
res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
}
/* enable temperature comparation */
}
/* enable temperature comparation */
+ 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);