diff mbox

[1/2] i2c: omap: fix NACK and Arbitration Lost irq handling

Message ID 1416014452-6712-1-git-send-email-al.kochet@gmail.com
State Superseded
Headers show

Commit Message

Alexander Kochetkov Nov. 15, 2014, 1:20 a.m. UTC
commit 1d7afc95946487945cc7f5019b41255b72224b70 (i2c: omap: ack IRQ in parts)
changed the interrupt handler to complete transfers without clearing
XRDY (AL case) and ARDY (NACK case) flags. XRDY or ARDY interrupt will be
fired again (in parallel with omap_i2c_xfer_msg). Interrupt handler will
complete transfers second time. As a result, NACK and AL transfers
terminates with "transfer timeout" and sometimes client code segfault.

The patch restore original logic of handling NACK and AL interrupts and
fix race between interrupt handler and omap_i2c_xfer_msg (for AL and
NACK case only).

Tested on Beagleboard XM C.

Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
---
 drivers/i2c/busses/i2c-omap.c |    2 --
 1 file changed, 2 deletions(-)

Comments

Felipe Balbi Nov. 15, 2014, 1:43 a.m. UTC | #1
On Sat, Nov 15, 2014 at 05:20:51AM +0400, Alexander Kochetkov wrote:
> commit 1d7afc95946487945cc7f5019b41255b72224b70 (i2c: omap: ack IRQ in parts)
> changed the interrupt handler to complete transfers without clearing
> XRDY (AL case) and ARDY (NACK case) flags. XRDY or ARDY interrupt will be
> fired again (in parallel with omap_i2c_xfer_msg). Interrupt handler will
> complete transfers second time. As a result, NACK and AL transfers
> terminates with "transfer timeout" and sometimes client code segfault.
> 
> The patch restore original logic of handling NACK and AL interrupts and
> fix race between interrupt handler and omap_i2c_xfer_msg (for AL and
> NACK case only).
> 
> Tested on Beagleboard XM C.
> 

Assuming this is really correct (I haven't tested), you need to add:

Fixes: 1d7afc9 i2c: omap: ack IRQ in parts
Cc: <stable@vger.kernel.org> # v3.7+

here and resend, so it gets backported to older kernels.

> Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
> ---
>  drivers/i2c/busses/i2c-omap.c |    2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index 90dcc2e..9af7095 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -926,14 +926,12 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
>  		if (stat & OMAP_I2C_STAT_NACK) {
>  			err |= OMAP_I2C_STAT_NACK;
>  			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
> -			break;
>  		}
>  
>  		if (stat & OMAP_I2C_STAT_AL) {
>  			dev_err(dev->dev, "Arbitration lost\n");
>  			err |= OMAP_I2C_STAT_AL;
>  			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
> -			break;
>  		}
>  
>  		/*
> -- 
> 1.7.9.5
>
Alexander Kochetkov Nov. 15, 2014, 2:48 a.m. UTC | #2
> Assuming this is really correct (I haven't tested), you need to add:

To help understanding logic, I'd like to provide event traces (with the patch applied):

See i2c-omap.c dc418f6e6a8f5021ccf9e9c0957eefae3737168d as a reference.
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/i2c/busses/i2c-omap.c?id=dc418f6e6a8f5021ccf9e9c0957eefae3737168d

Typical event sequence for Arbitration Lost case looks like:
addr: 0x0058, len: 4, flags: 0x1, stop: 1
omap_i2c_xfer_msg:564 (STAT=0x0140; IE=0x601f; CON=0x8200)
omap_i2c_xfer_msg:565 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
omap_i2c_xfer_msg:566 (STAT=0x0140; IE=0x601f; CON=0x8403)
omap_i2c_isr:886 (STAT=0x1141; IE=0x601f; CON=0x8000)
omap_i2c_isr_thread:906 (STAT=0x1141; IE=0x601f; CON=0x8000)
IRQ (ISR = 0x0001)
Arbitration lost

Typical event sequence for NACK case looks like:
addr: 0x0068, len: 4, flags: 0x1, stop: 1
omap_i2c_xfer_msg:564 (STAT=0x0040; IE=0x601f; CON=0x8000)
omap_i2c_xfer_msg:566 (STAT=0x0040; IE=0x601f; CON=0x8403)
omap_i2c_isr:886 (STAT=0x0146; IE=0x601f; CON=0x8000)
omap_i2c_isr_thread:906 (STAT=0x0146; IE=0x601f; CON=0x8000)
IRQ (ISR = 0x0006)
NACK
IRQ (ISR = 0x0004)
ARDY
omap_i2c_isr_thread:1030 (STAT=0x0140; IE=0x601f; CON=0x8000)

> 
> Fixes: 1d7afc9 i2c: omap: ack IRQ in parts
> Cc: <stable@vger.kernel.org> # v3.7+
> 
> here and resend, so it gets backported to older kernels.
> 

I'll resend. Thanks.




--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 90dcc2e..9af7095 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -926,14 +926,12 @@  omap_i2c_isr_thread(int this_irq, void *dev_id)
 		if (stat & OMAP_I2C_STAT_NACK) {
 			err |= OMAP_I2C_STAT_NACK;
 			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
-			break;
 		}
 
 		if (stat & OMAP_I2C_STAT_AL) {
 			dev_err(dev->dev, "Arbitration lost\n");
 			err |= OMAP_I2C_STAT_AL;
 			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
-			break;
 		}
 
 		/*