i2c-mv64xxx: Fix random oops at boot

I have a Marvell board which has the same i2c hw block than mv64xxx, so
I'm trying to use i2c-mv64xxx driver.

But I get the following random oops at boot:

Unable to handle kernel NULL pointer dereference at virtual address 00000002
Backtrace:
[<c0397e4c>] (mv64xxx_i2c_intr+0x0/0x2b8) from [<c02879c4>] (__do_irq+0x4c/0x8c)
[<c0287978>] (__do_irq+0x0/0x8c) from [<c0287c0c>] (do_level_IRQ+0x68/0xc0)
r8 = C0501E08 r7 = 00000005 r6 = C0501E08 r5 = 00000005
r4 = C048BB78
[<c0287ba4>] (do_level_IRQ+0x0/0xc0) from [<c02885f8>] (asm_do_IRQ+0x50/0x134)
r6 = C0449C78 r5 = F1020000 r4 = FFFFFFFF
[<c02885a8>] (asm_do_IRQ+0x0/0x134) from [<c02869c4>] (__irq_svc+0x24/0x100)
r8 = C1CAC400 r7 = 00000005 r6 = 00000002 r5 = F1020000
r4 = FFFFFFFF
[<c0287efc>] (setup_irq+0x0/0x124) from [<c02880d0>] (request_irq+0xb0/0xd0)
r7 = C041B2AC r6 = C0397E4C r5 = 00000000 r4 = 00000005
[<c0288020>] (request_irq+0x0/0xd0) from [<c03985f4>] (mv64xxx_i2c_probe+0x148/0x244)
[<c03984ac>] (mv64xxx_i2c_probe+0x0/0x244) from [<c038bedc>] (platform_drv_probe+0x20/0x24)


The oops is caused by a spurious interrupt that occurs when request_irq
is called. mv64xxx_i2c_fsm() tries to read drv_data->msg, which is NULL.

I noticed that hardware init is done after requesting irq. Thus any
pending irq from previous hardware usage may cause this.

The following patch fixes it:


Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Acked-by: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>

authored by Maxime Bizon and committed by Jean Delvare 3269bb63 b119dc3f

+2 -2
+2 -2
drivers/i2c/busses/i2c-mv64xxx.c
··· 529 platform_set_drvdata(pd, drv_data); 530 i2c_set_adapdata(&drv_data->adapter, drv_data); 531 532 if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, 533 MV64XXX_I2C_CTLR_NAME, drv_data)) { 534 dev_err(&drv_data->adapter.dev, ··· 543 "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); 544 goto exit_free_irq; 545 } 546 - 547 - mv64xxx_i2c_hw_init(drv_data); 548 549 return 0; 550
··· 529 platform_set_drvdata(pd, drv_data); 530 i2c_set_adapdata(&drv_data->adapter, drv_data); 531 532 + mv64xxx_i2c_hw_init(drv_data); 533 + 534 if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, 535 MV64XXX_I2C_CTLR_NAME, drv_data)) { 536 dev_err(&drv_data->adapter.dev, ··· 541 "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); 542 goto exit_free_irq; 543 } 544 545 return 0; 546